Operator new not overloaded for possibly overaligned class

Выделенное устройство хранения данных может быть меньшего размера, чем объектное требование выравнивания

Описание

Этот дефект происходит, когда вы не соответственно перегружаете оператор new/new[] и вы используете этот оператор, чтобы создать объект с требованием выравнивания, заданным с alignas. Средство проверки повышает дефект для этих версий броска и неброска оператора new/new[].

  • void* operator new(std::size_t size)

  • void* operator new(std::size_t size, const std::nothrow_t&)

  • void* operator new[](std::size_t size)

  • void* operator new[](std::size_t size, const std::nothrow_t&)

Использование alignas указывает, что вы не ожидаете оператор по умолчанию new/new[] удовлетворить требованию выравнивания или объекту, и что объект возможно по выровненному. Тип по выровненному, если вы используете alignas сделать требование выравнивания типа больше, чем std::max_align_t. Например, foo по выровненному в этом фрагменте кода, потому что его требование выравнивания составляет 32 байта, но std::max_align_t имеет выравнивание 16 байтов в большинстве реализаций.

struct alignas(32) foo {
  char elems[32];
}

Оператор, новый не перегруженный для возможно сверхвыровненного класса, не повышает дефекта, если вы не перегружаете оператор new/new[] и вы используете версию C++ 17 или позже Стандарта. Оператор по умолчанию new/new[] на C++ 17 или более поздние поддержки по выравниванию путем передачи требования выравнивания в качестве аргумента типа std::align_val_t, например, void* operator new(std::size_t size, std::align_val_t alignment).

Риск

Оператор по умолчанию new/new[] выделяет устройство хранения данных с требованием выравнивания std::align_val_t самое большее. Если вы не перегружаете оператор, когда вы создаете объект с по выровненному типу, полученный объект может быть неправильно выровнен. Доступ к этой объектной силе вызывает ошибки несанкционированного доступа или аварийные завершения программы.

Фиксация

Если вы используете версию C++ 14 или ранее Стандарта, передаете требование выравнивания по выровненным типам к оператору new/new[] путем перегрузки оператора.

Примеры

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

#include <new>
#include <cstdlib>
#include <iostream>

struct alignas(64) foo {
    char elems[32];
};

foo*  func()
{
    foo*  bar = 0x0;
    try {
        bar =  new  foo ;
    } catch (...) { return nullptr; }
    delete bar;
}

В этом примере, структура foo объявляется с требованием выравнивания 32 байтов. Когда вы используете оператор по умолчанию new создать объект bar, выделенная память для bar меньше, чем требование выравнивания типа foo и bar может быть неправильно выровнен.

Коррекция — задает перегруженный оператор new обрабатывать требование выравнивания типа foo

Одна возможная коррекция, если вы используете C11 stdlib.h или POSIX-C malloc.h, должен задать перегруженный оператор new это использует aligned_alloc() или posix_memalign() или получить устройство хранения данных с правильным выравниванием.

#include <new>
#include <cstdlib>
#include <iostream>

struct alignas(64) foo {
    char elems[32];
    static void* operator new (size_t nbytes)
    {
        if (void* p =
                ::aligned_alloc(alignof(foo), nbytes)) {
            return p;
        }
        throw std::bad_alloc();
    }
    static void operator delete(void *p) {
        free(p);
    }
};

foo*  func()
{
    foo*  bar = 0x0;
    try {
        bar =  new  foo ;
    } catch (...) { return nullptr; }
    delete bar;
} 

Информация о результате

Группа: объектно-ориентированный
Язык: C++
Значение по умолчанию: На для рукописного кода, прочь для сгенерированного кода
Синтаксис командной строки: MISSING_OVERLOAD_NEW_FOR_ALIGNED_OBJ
Удар: носитель
Введенный в R2019b