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