在微处理器中,据说局部变量存储在堆栈中。在我的例子中,如果func1((被主函数调用,那么局部变量(int a=12;(将在堆栈中创建。一旦调用函数被执行,并返回到主函数,堆栈内存将被删除。因此指针地址仍然保持(*b(值12。在堆栈中,如果这个"a=12"被删除,那么"b"应该是一个悬空指针否??有人能解释一下吗?如果您对执行此代码时内存中发生的情况有详细的解释,那将很有帮助。
#include <stdio.h>
int* func1(void);
int main()
{
int* b = func1();
printf("%dn",*b);
}
int* func1(void)
{
int a = 12;
int* b = &a;
return b;
}
指针悬空。内存可能仍然保存以前的值,但取消引用指针会调用未定义的行为。
如果您通过-Wall
选项,GCC将对此发出警告。
来自C标准(6.2.4(:
对象的生存期是在该存储被保证为其保留。对象存在,具有恒定地址,25(并保留其最后存储的值26(如果一个对象在其生命周期之外被引用终身,行为是未定义的。指针的值变为当它指向的对象到达其末端时不确定一生
这里有多个层。
首先,是C编程语言。这是一种语言。你在里面说些什么,它就有意义。有些句子是有意义的,但你也可以构建语法有效的胡言乱语句子。
你发布的代码,语法有效,是胡言乱语。当函数返回时,func1
中的对象a
停止存在。*b
尝试访问一个不再存在的对象。它没有定义在对象的生存期结束后访问对象时应该发生什么。您可以阅读有关未定义行为的信息。
内存存在。当函数返回时,它并不是被分解的。RAM芯片并不是从你的电脑里掉出来的。它们仍然在那里。
因此,编译器将生成一些机器指令。将执行这些机器指令。仅取决于编译器的决定(代码是未定义的行为,编译器可以随心所欲(,实际代码可以以编译器决定的任何方式进行行为。但是,最有可能的是,*b
将生成机器指令,读取对象a
所在的内存区域。该存储器区域可能仍然保持值12
,或者它在返回func1
和调用printf
之间的某个地方被覆盖,导致读取一些其他值。
在堆栈中,如果删除了这个"a=12",那么"b"应该是一个悬空指针否?
是。
当此代码时,内存中会发生什么
这取决于编译器生成的实际机器指令。编译代码并检查程序集。
严格来说,行为是未定义的,但在printf
之后重复printf
或以其他方式检查(例如在调试器中(*b
。很可能它将不再是12
。
说堆栈存储器是"非易失性"是不准确的;删除";。相反,堆栈指针会恢复到调用之前的地址。内存在其他方面是未受影响的,但可供后续调用使用(或用于向此类调用传递参数(,因此在调用printf
之后,它很可能已被重用和修改。
所以是的,指针是";悬挂的";因为它指向的是不再是"0"的存储器;有效的";从某种意义上说,它不属于指针所在的上下文。