ПроблемаРазмещение нового используемого с недостаточным объемом памяти или несовпадающими указателями происходит, когда указатель передается в new размещения оператор не имеет достаточного объема памяти для выделения памяти или не выровнен должным образом.
Предположим, что указатель ptr предварительно выделено m байты памяти в стеке и имеет n выравнивания. Для образца, если ptr массив:
выделенное хранилище
sizeof(uint8_t) * 5 и выравнивание
alignof(uint8_t). Если вы выделяете больше
m байты на этот указатель в
new размещения
выражение или если выравнивание, необходимое для выделения, больше
nШашка вызывает нарушение. При определении выравнивания указателя на шашку учитываются явные выравнивания, такие как с
std::align.
Средство проверки не рассматривает указатели, которые являются предварительно выделенной памятью на куче, поскольку доступное хранилище зависит от доступности памяти, которая известна только во время выполнения.
РискThe new оператор выделяет необходимый объем памяти для хранения объекта на куче и создает новый объект в выделенной памяти за одну операцию. Если вы хотите разделить выделение и конструкцию и поместить объект в предварительно выделенную память или в стек, или в кучу, вы используете размещение new. Размещение new имеет преимущества перед new в определенных ситуациях, например, когда необходимо поместить объект в известное место памяти.
The new оператор автоматически выделяет правильный объем выровненной памяти, необходимый объекту. Но при использовании new размещениянеобходимо вручную убедиться, что переданный указатель имеет достаточную выделенную емкость памяти и правильно выровнен. Нарушение этих ограничений приводит к конструкции объекта в несогласованном местоположении или инициализации памяти за пределами выделенных границ, что может привести к неожиданному или зависящему от реализации поведению.
ЗафиксироватьУбедитесь, что указатель используется в new размещения операция имеет достаточную память для выделения, и выравнивания совпадают.
Пример - new размещения Используется с недостаточной емкостью памяти и несовпадающими указателями#include <new>
#include<memory>
#include <cstdint>
void Foo()
{
uint8_t c;
uint64_t* ptr =
new // Non-compliant (insufficient storage, misaligned)
(&c) uint64_t;
}
void Bar()
{
uint8_t buf[sizeof(uint64_t)];
uint64_t* ptr =
new // Non-compliant (sufficient storage, misaligned)
(buf) uint64_t;
}
void Baz()
{
void* buf;
std::size_t sp = 64;
std::align(alignof(uint64_t), sizeof(uint64_t), buf, sp);
uint64_t* ptr =
new // Compliant (sufficient storage, aligned)
(buf) uint64_t;
}В функциональном Foo, а &c указывает на uint8_t и имеет одну байтовую память в стеке с однобайтовым выравниванием. Указатель передается в new размещения, который создает образец uint64_t для этого требуется 8 байт памяти и 4-байтовое выравнивание. Это использование нарушает правило.
В функциональном Bar, указатель buf правильно выделен и имеет достаточную емкость для хранения. Но, потому что это указывает на uint8_t тип данных, он имеет однобайтовое выравнивание. Это использование все еще нарушает правило.
Функция Baz вызывает std::align функция для создания указателя с правильной емкостью памяти (8 байт) и выравниванием (4 байта) для uint64_t. Это использование соответствует правилу.