exponenta event banner

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/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[] перегрузкой оператора.

Пример - Выделенная память меньше требования к выравниванию типа 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 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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