ПроблемаРазмещение нового используемого с недостаточным объемом памяти или несовпадающими указателями происходит, когда указатель передается в 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
. Это использование соответствует правилу.