Почему переменная C++ не удаляется сразу?

Я хотел бы знать, почему данные, на которые указывают, когда вы возвращаетесь из функции, не удаляются сразу. В приведенном ниже фрагменте кода я ожидаю, что когда я возвращаю адрес x указателю, чтобы инициализировать его при возврате из функции, данные, хранящиеся в адресе x, должны быть немедленно удалены. Тем не менее, я все еще могу получить правильное значение в main и только после еще одной строки кода оно вдруг превращается в мусор? Почему это не происходит сразу

int* function(int x)
{
    cout << x << endl; // This outputs 5 as expected
    return &x;
}

int main()
{
    int* a = function(5);


    cout << *a; // This still outputs 5. Why?
    cout << endl;

    cout << *a; // It is garbage here as expected
    cout << endl;

    return 0;
}

Спасибо

4 ответа

Решение

Возврат адреса локальной переменной вызывает неопределенное поведение. Итак, вам просто повезло.

Локальная переменная (размещенная в стеке) удаляется, когда она покидает область видимости, а в вашем случае это когда function() заканчивается. Однако после того, как переменная покидает область, занимаемая ею память не перезаписывается сразу, и если в этой памяти не используется значение x останется там.

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

Адрес возврата локальной переменной не определен. Неопределенный означает, что вы не можете предсказать, будет ли он выводить правильный или неправильный результат. К сожалению, вы получили правильный результат.

Поскольку вам не следует обращаться к такому "мусору" (техническому термину), система свободна справляться с ним так, как считает нужным. Например, могли быть другие задачи, выполнение которых повлияло бы на правильно написанные программы.

Когда вы возвращаете адрес локальной переменной, результирующий указатель "болтается"; доступ через висячий указатель или даже просто чтение его - неопределенное поведение. Это означает, что в теории все может случиться. На практике скомпилированный код не будет возвращать память локальных переменных в функции в ОС; в большинстве операционных систем это невозможно, даже если бы захотелось. Таким образом, память просто сидит там, пока кто-то еще не использует ее. В случае памяти в функции, она будет использоваться повторно при вызове другой функции; до этого вы, вероятно, сможете получить к нему доступ и найти старые значения. Отладочные сборки могут быть преднамеренно закрашены в памяти при выходе из функции, но основные компиляторы не делают этого. И, конечно, такие программы, как valgrind, могут проверять правильность указателя и регистрировать ошибку (но я не знаю, действительно ли valgrind улавливает это).

Другие вопросы по тегам