AUTOSAR C++14 Rule A18-5-10

Новое размещение должно использоваться только с правильно выровненными указателями на достаточную емкость памяти

Описание

Управляйте определением

Новое размещение должно использоваться только с правильно выровненными указателями на достаточную емкость памяти.

Объяснение

new оператор выделяет необходимое количество памяти для того, чтобы хранить объект на куче и создает новый объект в выделенной памяти в одной операции. Если вы хотите разделить выделение и конструкцию и поместить объект в предварительно выделенную память или на стеке или на куче, вы используете размещение new. Размещение new имеет преимущества перед new в определенных ситуациях, например, когда необходимо поместить объект в известной ячейке памяти.

new оператор автоматически выделяет правильную сумму выровненной памяти, которой требует объект. Но при использовании размещения new, необходимо вручную убедиться, что указатель, который вы передаете, имеет достаточную выделенную емкость памяти и правильно выравнивается. Нарушение этих ограничений приводит к конструкции объекта в неправильно выровненном местоположении или инициализации памяти за пределами выделенных границ, которые могут привести к неожиданному или зависящему от реализации поведению.

Реализация Polyspace

Предположим что указатель ptr предварительно выделенный m байты памяти на стеке и имеют выравнивание n. Например, если ptr массив:

uint8_t ptr[5];
выделенным устройством хранения данных является sizeof(uint8_t) * 5 и выравниванием является alignof(uint8_t). Если вы выделяете больше, чем m байты к этому указателю в размещении new выражение или если выравнивание, требуемое для выделения, больше n, средство проверки повышает нарушение. При определении выравнивания указателя средство проверки учитывает явные выравнивания такой как с std::align.

Средство проверки не рассматривает указатели, которые являются предварительно выделенной памятью на куче, поскольку доступное устройство хранения данных зависит от доступности памяти, которая известна только во время выполнения.

Поиск и устранение проблем

Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.

Примеры

развернуть все

#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. Это использование выполняет правило.

Проверяйте информацию

Группа: вспомогательная библиотека Языка
Категория: необходимый, автоматизированный
Введенный в R2020b