Pointer or reference to stack variable leaving scope

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

Описание

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

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

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

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

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

  • (C++ 11 и более поздние версии) Функция возвращает объект лямбда-выражения, который захватывает локальные переменные функции по ссылке.

Дефект также относится к памяти, выделенной с помощью 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);
}

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

Группа: Статическая память
Язык: C | C++
По умолчанию: On для рукописного кода, off для сгенерированного кода
Синтаксис командной строки: LOCAL_ADDR_ESCAPE
Влияние: Высокий
ИДЕНТИФИКАТОР CWE: 562, 825
Введенный в R2015b