CERT C++: DCL30-C

Объявление объектов с соответствующими сроками хранения

Описание

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

Объявление объектов с соответствующей продолжительностью хранения.[1]

Реализация Polyspace

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

Примеры

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

Проблема

Указатель или ссылка на переменную стека, покидающую возможности, происходит, когда указатель или ссылка на локальную переменную покидает возможности переменной. Для образца:

  • Функция возвращает указатель на локальную переменную.

  • Функция выполняет назначение globPtr = &locVar. globPtr является переменной глобального указателя и locVar является локальной переменной.

  • Функция выполняет назначение *paramPtr = &locVar. paramPtr является параметром функции, который, для образца, является int** указатель и locVar является локальным int переменная.

  • Метод C++ выполняет назначение memPtr = &locVar. memPtr является представителем данных указателя класса, которому принадлежит метод. locVar является локальной переменной метода.

Дефект также относится к памяти, выделенной с помощью alloca функция. Дефект не применяется к статическим локальным переменным.

Риск

Локальным переменным выделяется адрес в стеке. Когда возможности локальной переменной заканчиваются, этот адрес доступен для повторного использования. Использование этого адреса для доступа к локальному значению переменных вне переменных возможностей может вызвать неожиданное поведение.

Если указатель на локальную переменную покидает возможности переменной, Polyspace® Bug Finder™ подсвечивает дефект. Дефект появляется, даже если вы не используете адрес, сохраненный в указателе. Для поддерживаемого кода рекомендуется не позволять указателю покидать возможности переменной. Даже если вы не используете адрес в указателе сейчас, кто-то другой, использующий вашу функцию, может использовать адрес, вызывая неопределенное поведение.

Зафиксировать

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

Пример - Указатель на локальную переменную, возвращенную из функции
void func2(int *ptr) {
    *ptr = 0;
}

int* func1(void) {
    int ret = 0;
    return &ret ;
}
void main(void) {
    int* ptr = func1() ;
    func2(ptr) ;
}

В этом примере func1 возвращает указатель на локальную переменную ret.

В main, ptr указывает на адрес локальной переменной. Когда ptr доступ осуществляется в func2, доступ запрещен, потому что возможности ret ограничивается func1,

Пример - Указатель на локальную переменную избегает через выражение Лямбды
auto createAdder(int amountToAdd) {
  int addThis = amountToAdd;
  auto adder = [&] (int initialAmount) {
      return (initialAmount + addThis);
  };
  return adder;
}
 
void func() {
  auto AddByTwo = createAdder(2);
  int res = AddByTwo(10);
}

В этом примере createAdder функция задает лямбда-выражение adder который захватывает локальную переменную addThis по ссылке. Область возможностей addThis ограничивается createAdder функция. Когда объект вернулся createAdder вызывается, ссылка на переменную addThis доступ к нему за пределами его возможностей. При доступе таким способом значение addThis не определено.

Коррекция - Захватывайте локальные переменные путем копирования в выражении Лямбда вместо ссылки

Если функция возвращает объект выражения лямбды, избегайте захвата локальных переменных путем ссылки в объекте лямбды. Вместо этого соберите переменные путем копирования.

Переменные, захваченные копией, имеют то же время жизни, что и лямбда- объект, но переменные, захваченные ссылкой, часто имеют меньшее время жизни, чем сама лямбда объекта. Когда используется объект lambda, эти переменные, доступные вне возможностей, имеют неопределенные значения.

auto createAdder(int amountToAdd) {
  int addThis = amountToAdd;
  auto adder = [=] (int initialAmount) {
      return (initialAmount + addThis);
  };
  return adder;
}
 
void func() {
  auto AddByTwo = createAdder(2);
  int res = AddByTwo(10);
}

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

Группа: 01. Объявления и инициализация (DCL)
Введенный в R2019a

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

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

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