exponenta event banner

Правило AUTOSAR C++ 14 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