2 sinat 14884161 sinat_14884161 于 2016.03.31 12:07 提问

C++局部指针困惑,该程序为什么能正常输出

int* pointBoom()//局部变量指针测试
{
int c = 20;
int *f = &c;//局部变量指针f
cout << "局部变量c的地址" << &c<<endl;
cout << "局部变量f存储的地址" << f<<endl;
cout << "局部变量f的地址" << &f<<endl;

return f;

}
int main()
{
cout << "调用函数pointBoom" << endl;
cout << "pointBoom的值是" << *pointBoom() << endl;
cout << "pointBoom中返回的地址是" << pointBoom() << endl;//第二次调用
return 0;
}

为什么程序正常,f指向的c是局部变量,c是在栈上分配的,函数调用结束后,不是销毁了么,f指向的内存地址中存储的变量不是为空么。为什么还能正常输出呢?

13个回答

zuishikonghuan
zuishikonghuan   2016.03.31 13:54

这不难理解,对于绝大部分的实现(编译器)而言,他们是这样处理的:当函数调用时,总要遵循一种“调用约定”,对于大多数的调用约定而言,首先是参数入栈(可能有部分参数用寄存器传送),然后返回地址入栈(x86上就是把cs:eip入栈 ),CPU执行现场跳转,以C语言默认调用约定 __cdecl 为例,函数会用 push ebp 指令把ebp寄存器入栈,然后保存堆栈指针,即调用 mov ebp,esp 然后做一些工作,局部变量也在堆栈上面,然后就是函数里的代码了,就是你写的C/C++代码被编译器编译后的机器码,函数的最后三条指令通常是:mov esp,ebp ;pop ebp ;ret 。也就是说,函数只是简单的用ebp中存储的“栈顶指针”恢复到esp(x86CPU上用来存储栈顶指针的寄存器),这样就是平衡堆栈了。并没有把堆栈上的数据清零,所以在main函数里面,如果没有再使用这一部分堆栈(如调用其他函数)这时候的数据还是原来的。

qq423399099
qq423399099   Ds   Rxr 2016.03.31 12:34

内存释放并不会对内存清零。它只是说该段内存可以被其它地方使用了。如果该段内存被其它使用并改写,你打印的值就变了。(野指针也是指针,只是说他指向的内容有可能被其它地方改变)。
指针指着一个生命周期结束的变量不仅可以访问,还可以修改,只不过这种访问是不确定的
局部变量的地址都是在程序自己的堆栈中,当局部变量结束后,只要没有将该局部变量的内存地址给别的变量,其值仍然存在。但如果修改的话,是比较危险的,因为这个内存地址可能给了程序的其它变量,通过指针强行修改的话,可能会引起程序崩溃

yanghuajia
yanghuajia   2016.03.31 12:47

栈上的内存通常是在程序开始时一次性分配的,所有一直都在,不会被释放。指向栈的指针几乎一定能用

u012032441
u012032441   2016.03.31 13:35

用我的理解说个通俗的比喻哈,不对的话请指正
这就好像你去开房(内存)的时候领了一把钥匙,你退房走人了没交钥匙(返回了指向局部变量的指针),但是房间还在,并不是你一退房房间也一起消失了
可是你之后再用这把钥匙访问的时候里面可能已经住了别人,你这种访问就是非常“不安全”的,所以要避免这种访问的发生
但你刚走,那个房间还没分给别人,这时你落在里面的手机还是在里面的,这就是为啥你这个程序还能正常输出

lm_whales
lm_whales   Rxr 2016.03.31 14:09

内存有几种使用情况
1,被占用 通常函数调用会占用栈内存,变量定义会占用栈,静态区,内存
2,动态分配会占用 堆内存,你同时要用一个指针对象保存它,以便使用
3,代码一直占用代码区内存
所谓内存分配。一般是指
1)给某个名字(变量,数组等对象)安排一个位置,以便存取,这是系统自动分配的
2)动态分配内存,系统划拨一块没有名字的内存,程序一般用指针接收(直接简介和有名字的对象建立联系)
这是程序员手动写代码,分配的内存。

u012032441
u012032441   2016.03.31 13:35

用我的理解说个通俗的比喻哈,不对的话请指正
这就好像你去开房(内存)的时候领了一把钥匙,你退房走人了没交钥匙(返回了指向局部变量的指针),但是房间还在,并不是你一退房房间也一起消失了
可是你之后再用这把钥匙访问的时候里面可能已经住了别人,你这种访问就是非常“不安全”的,所以要避免这种访问的发生
但你刚走,那个房间还没分给别人,这时你落在里面的手机还是在里面的,这就是为啥你这个程序还能正常输出

u012032441
u012032441   2016.03.31 13:34

用我的理解说个通俗的比喻哈,不对的话请指正
这就好像你去开房(内存)的时候领了一把钥匙,你退房走人了没交钥匙(返回了指向局部变量的指针),但是房间还在,并不是你一退房房间也一起消失了
可是你之后再用这把钥匙访问的时候里面可能已经住了别人,你这种访问就是非常“不安全”的,所以要避免这种访问的发生
但你刚走,那个房间还没分给别人,这时你落在里面的手机还是在里面的,这就是为啥你这个程序还能正常输出

u012032441
u012032441   2016.03.31 13:35

用我的理解说个通俗的比喻哈,不对的话请指正
这就好像你去开房(内存)的时候领了一把钥匙,你退房走人了没交钥匙(返回了指向局部变量的指针),但是房间还在,并不是你一退房房间也一起消失了
可是你之后再用这把钥匙访问的时候里面可能已经住了别人,你这种访问就是非常“不安全”的,所以要避免这种访问的发生
但你刚走,那个房间还没分给别人,这时你落在里面的手机还是在里面的,这就是为啥你这个程序还能正常输出

u012032441
u012032441   2016.03.31 13:35

用我的理解说个通俗的比喻哈,不对的话请指正
这就好像你去开房(内存)的时候领了一把钥匙,你退房走人了没交钥匙(返回了指向局部变量的指针),但是房间还在,并不是你一退房房间也一起消失了
可是你之后再用这把钥匙访问的时候里面可能已经住了别人,你这种访问就是非常“不安全”的,所以要避免这种访问的发生
但你刚走,那个房间还没分给别人,这时你落在里面的手机还是在里面的,这就是为啥你这个程序还能正常输出

u012032441
u012032441   2016.03.31 13:35

用我的理解说个通俗的比喻哈,不对的话请指正
这就好像你去开房(内存)的时候领了一把钥匙,你退房走人了没交钥匙(返回了指向局部变量的指针),但是房间还在,并不是你一退房房间也一起消失了
可是你之后再用这把钥匙访问的时候里面可能已经住了别人,你这种访问就是非常“不安全”的,所以要避免这种访问的发生
但你刚走,那个房间还没分给别人,这时你落在里面的手机还是在里面的,这就是为啥你这个程序还能正常输出

共13条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!