我遇到了this page,它说明了创建悬空指针的常用方法。
下面的代码用于通过返回局部变量的地址来说明悬空指针:
// The pointer pointing to local variable becomes
// dangling when local variable is static.
#include<stdio.h>
int *fun()
{
// x is local variable and goes out of scope
// after an execution of fun() is over.
int x = 5;
return &x;
}
// Driver Code
int main()
{
int *p = fun();
fflush(stdout);
// p points to something which is not valid anymore
printf("%d", *p);
return 0;
}
运行时,这是我得到的编译器警告(正如预期的那样):
In function 'fun':
12:2: warning: function returns address of local variable [-Wreturn-local-addr]
return &x;
^
这是我得到的结果(目前为止很好):
32743
然而,当我注释掉fflush(stdout)行时,这是我得到的输出(具有相同的编译器警告):
5
这种行为的原因是什么? fflush命令的存在/不存在究竟是如何导致此行为发生变化的?
答案 0 :(得分:3)
正如您所提到的,返回指向堆栈中对象的指针是不好的。您只看到fflush()
来电问题的原因是,如果不存在,则堆栈未经修改。也就是说,5
仍然存在,因此指针取消引用仍会向您提供5
。如果你在fun
和printf
之间调用一个函数(几乎可能是任何函数),它几乎肯定会覆盖那个堆栈位置,这使得后面的解引用会返回那个函数发生的垃圾。< / p>
答案 1 :(得分:0)
这是因为调用fflush(stdout)
会写入x
所在的堆栈。
让我解释一下。汇编语言中的堆栈(所有编程语言最终以某种方式运行)通常用于存储局部变量,返回地址和函数参数。当一个函数被调用时,它会把这些东西推到堆栈上:
然后,只需更改CPU认为堆栈顶部的位置,就可以逐个从堆栈中弹出这些内容。这意味着数据仍然存在,但不能保证继续存在。
在fun()
之后调用另一个函数会覆盖堆栈顶部之上的先前值,在这种情况下使用值stdout
,因此指针的引用值会发生变化。
如果不调用另一个函数,数据将保留在那里,并且在取消引用指针时仍然有效。