C中的悬空指针

我在C中编写了一个悬挂指针的程序。

#include int *func(void) { int num; num = 100; return # } int func1(void) { int x,y,z; scanf("%d %d",&y,&z); x=y+z; return x; } int main(void) { int *a = func(); int b; b = func1(); printf("%d\n",*a); return 0; } 

即使指针悬空,我也将输出设为100

我在上面的函数func1()做了一个更改。 现在我在编译时分配值,而不是像上面的程序那样从标准输入中获取yz的值。

我重新定义了func1() ,如下所示:

 int func1(void) { int x,y,z; y=100; z=100; x=y+z; return x; } 

现在输出是200

有人可以解释一下上述两项产出的原因吗?

未定义的行为意味着任何事情都可能发生,包括它会像你期望的那样。 在这种情况下,您的堆栈变量不会被覆盖。

 void func3() { int a=0, b=1, c=2; } 

如果在func1printf之间包含对func3()的调用,则会得到不同的结果。

编辑:在某些平台上实际发生了什么。

 int *func(void) { int num; num = 100; return # } 

为简单起见,假设在调用此函数之前堆栈指针为10,并且堆栈向上增长。

当您调用该函数时,返回地址被压入堆栈(位置10)并且堆栈指针递增到14(是的,非常简化)。 然后在位置14的堆栈上创建变量num,并且堆栈指针递增到18。

返回时,返回指向地址14的指针 – 从堆栈中弹出返回地址,堆栈指针返回10。

 void func2() { int y = 1; } 

在这里,同样的事情发生了。 在位置推送的返回地址,在位置14创建的y,为y分配1(写入地址14),返回并将指针堆叠回到位置10。

现在,你的旧int *func返回到地址14,对该地址的最后修改是func2的局部变量赋值。 所以,你有一个悬空指针(堆栈中位置10以上没有任何内容有效)指向调用func2的剩余值

这是因为内存的分配方式。

在调用func并返回一个悬空指针后,堆栈中存储num的部分仍然具有值100 (这是您之后看到的)。 我们可以根据观察到的行为得出这个结论。

在更改之后,看起来发生的事情是func1调用覆盖a指向func1内部的添加结果的内存位置(之前用于func的堆栈空间现在由func1重用),所以这就是你看到的原因200。

当然, 所有这些都是未定义的行为,所以虽然这可能是一个很好的哲学问题,回答它并不能真正为你买任何东西。

这是未定义的行为。 它现在可以在您的计算机上正常工作,从现在开始20分钟,可能会在一小时内崩溃,等等。一旦另一个对象在堆栈上占据相同的位置,就会出现num ,您将注定失败

悬空指针(指向已被解除关联的位置的指针)会导致未定义的行为 ,即任何事情都可能发生。

特别是,内存位置在func1 偶然重用*。 结果取决于堆栈布局,编译器优化,体系结构,调用约定和堆栈安全机制。

使用悬空指针,程序的结果是不确定的。 这取决于堆栈和寄存器的使用方式。 使用不同的编译器,不同的编译器版本和不同的优化设置,您将获得不同的行为。

返回指向局部变量的指针会产生未定义的行为,这意味着程序执行的任何操作(任何内容)都是有效的。 如果你得到了预期的结果,那就是运气不好。

请从基础C学习function。你的概念是有缺陷的… main应该是

 int main(void) { int *a = func(); int b; b = func1(); printf("%d\n%d",*a,func1()); return 0; } 

这将输出100 200