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