ПроблемаУказатель или ссылка на переменную стека, покидающую область, возникает, когда указатель или ссылка на локальную переменную выходит из области действия переменной. Например:
Функция возвращает указатель на локальную переменную.
Назначение выполняется функцией 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 не определен.
Исправление - захват локальных переменных копированием в лямбда-выражении вместо ссылкиЕсли функция возвращает объект лямбда-выражения, избегайте захвата локальных переменных по ссылке в лямбда-объекте. Захватите переменные путем копирования.
Переменные, захваченные копией, имеют тот же срок службы, что и лямбда-объект, но переменные, захваченные ссылкой, часто имеют меньший срок службы, чем сам лямбда-объект. При использовании лямбда-объекта эти переменные, доступные вне области действия, имеют неопределенные значения.
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);
}