CERT C++: MEM57-CPP

Избегайте использования оператора по умолчанию new для выровненных по периметру типов

Описание

Определение правила

Избегайте использования оператора по умолчанию new для выровненных по периметру типов.[1]

Реализация Polyspace

Эта проверка проверяет, является ли оператор новым, не перегруженным, для возможно переопределенного класса.

Примеры

расширить все

Проблема

Новый не перегруженный оператор для возможно переравнивающегося класса возникает, когда вы не перегружаете оператор должным образом 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 not perloaded для возможно переопределенного класса не повышает дефект, если вы не перегрузите оператор 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 или более раннюю версию Standard, передайте требование выравнивания по выровненным типам оператору new/new[] путем перегрузки оператора.

Пример - Выделенная память меньше, чем требование выравнивания типа foo
#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;
} 

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

Группа: Правило 06. Управление памятью (MEM)
Введенный в R2019b

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОН И/ИЛИ ЕГО ИНЖЕНЕРНОГО ИНСТИТУТА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ НА БАЗИСЕ «КАК ЕСТЬ». УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБОГО ВОПРОСА, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЮ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ КОММЕРЧЕСКОЙ ВЫГОДЫ, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Это программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллон или его Институтом программной инженерии.