我有下面的代码。

#include <iostream>

int * foo()
{
    int a = 5;
    return &a;
}

int main()
{
    int* p = foo();
    std::cout << *p;
    *p = 8;
    std::cout << *p;
}

并且代码正在运行,没有运行时异常!

输出是58

怎么可能呢?局部变量的内存在其函数之外不是不可访问的吗?


当前回答

因为存储空间还没有被践踏。不要指望那种行为。

其他回答

给所有的答案补充一点:

如果你这样做:

#include<stdio.h>
#include <stdlib.h>
int * foo(){
    int a = 5;
    return &a;
}
void boo(){
    int a = 7;

}
int main(){
    int * p = foo();
    boo();
    printf("%d\n",*p);
}

输出可能是:7

这是因为从foo()返回后,堆栈被释放,然后被boo()重用。 如果你分解可执行文件,你会清楚地看到它。

你的问题与范围无关。在你所展示的代码中,函数main看不到函数foo中的名称,所以你不能在foo之外直接使用这个名称访问foo中的a。

您遇到的问题是为什么程序在引用非法内存时不发出错误信号。这是因为c++标准在非法内存和合法内存之间没有明确的界限。引用弹出堆栈中的内容有时会导致错误,有时不会。视情况而定。不要指望这种行为。假设在编程时它总是会导致错误,但在调试时它永远不会发出错误信号。

这是典型的未定义行为,两天前在这里讨论过——搜索一下网站。简而言之,您是幸运的,但是任何事情都可能发生,并且您的代码正在对内存进行无效的访问。

您实际上调用了未定义的行为。

返回临时作品的地址,但由于临时作品在函数的末尾被销毁,访问它们的结果将是未定义的。

因此,您没有修改a,而是修改了a曾经所在的内存位置。这种差异与崩溃和不崩溃之间的差异非常相似。

It's 'Dirty' way of using memory addresses. When you return an address (pointer) you don't know whether it belongs to local scope of a function. It's just an address. Now that you invoked the 'foo' function, that address (memory location) of 'a' was already allocated there in the (safely, for now at least) addressable memory of your application (process). After the 'foo' function returned, the address of 'a' can be considered 'dirty' but it's there, not cleaned up, nor disturbed/modified by expressions in other part of program (in this specific case at least). A C/C++ compiler doesn't stop you from such 'dirty' access (might warn you though, if you care). You can safely use (update) any memory location that is in the data segment of your program instance (process) unless you protect the address by some means.