[问题] 请问local变量在离开stack后为何能存取

楼主: Keitaro (动き出す时间...)   2021-04-01 21:54:38
开发平台(Platform): (Ex: Win10, Linux, ...)
win10/debian
编译器(Ex: GCC, clang, VC++...)+目标环境(跟开发平台不同的话需列出)
VC2008/gcc
程式码(Code):(请善用置底文网页, 记得排版,禁止使用图档)
#include <stdio.h>
struct StructB
{
int m_nB;
StructB()
{
m_nB = 0;
}
~StructB()
{
printf("~StructB()\n");
}
};
struct StructA
{
StructA()
{
m_pB = NULL;
}
StructB *m_pB;
};
void foo(StructA &p_stA)
{
StructB stB;
stB.m_nB = 1;
p_stA.m_pB = &stB;
}
int main()
{
StructA stA;
foo(stA);
printf("stA.m_pB->m_nB = %d\n", stA.m_pB->m_nB);
printf("stA.m_pB->m_nB = %d\n", stA.m_pB->m_nB); // 连续两次看结果
return 0;
}
补充说明(Supplement):
今天工作上我看到project code有很明显的问题如下.
有一个struct其中一个member是一个pointer,
这个struct产生一个member object放在一个class里面.
而我寻找这个pointer并没有任何地方去new物件出来,
而是直接在一个function里面产生一个local变量,
然后把local变量的位址设定给这个pointer.
问题来了, 设定local变量给这个struct的pointer,
然后离开这个function回到上一层stack, local变量不就free掉了吗?
再去存取这个struct pointer不是应该就会出问题?
但结果没有, 我用VC debug看程式竟然还能存取到正确的值.
这让我对以前变量lifecycle学习产生了质疑,
因此我直接写了上方简单的程式码来验证这件事.
我分别用VC以及gcc在win10/debian底下去执行上面的程式码,
神奇的事发生了
win10:
第一次printf看到印出的值正确为1, 第二次变为-2.
debain:
两次都为1.
我确认StructB的解构式已经"先"印出来才印出数值,
为何被free的变量还能存取到他的数值呢?
请版上先进指教, 谢谢。
作者: nh60211as   2021-04-01 21:57:00
你运气好(不好)
作者: LPH66 (-6.2598534e+18f)   2021-04-01 21:57:00
就只是单纯当时分给他的位置还没人来而已
作者: Lipraxde (Lipraxde)   2021-04-01 21:58:00
写出 UB 就是爽,一直写 UB 一直爽是 undefined behavior 没错,不过你这个例子,compiler 应该会报 warning / error 吧?
作者: ando5566 (风云变色)   2021-04-01 22:56:00
并没有free掉 ,stack pointer 和base pointer回到上一个function的状态,你在callee之后宣蹷@个大的阵列即可把stack memory洗掉。
作者: Lipraxde (Lipraxde)   2021-04-01 23:57:00
差别是放在 stack 上还说 heap 上如果有 address sanitizer 可以用的话开起来应该也可以在执行时跳出错误
作者: sarafciel (Cattuz)   2021-04-02 00:19:00
严格说起来是你的rsp/rbp改掉的时候就算release了只是release不代表你的local variable值一定会改变
作者: b0920075 (Void)   2021-04-02 00:33:00
有没有洗掉不是很重要,就算他没被洗掉你也不应该去用,谁知道等下还会不会留着
作者: sarafciel (Cattuz)   2021-04-02 01:52:00
你对free跟lifecycle消灭的定义是什么呢?是执行期当你access这块内存时 程式应该要报错吗?
作者: Lipraxde (Lipraxde)   2021-04-02 02:31:00
Compiler 没偷做什么,顶多说是偷懒没把 stack 刷掉
作者: a1u1usul3 (Q-Max)   2021-04-02 04:14:00
为什么删除的档案还有机会找回来?因为刚好没被洗掉。为什么上一个function里面local variable还在?因为刚好没被洗掉compiler没有偷做什么,他只是不再使用这个地方而已。既然已经不再使用这里也就不用特地清成0了
作者: ando5566 (风云变色)   2021-04-02 08:17:00
先执行destructor ,再离开当下function (做stk /bsp restore) ,最后pop pc+1 与jump ;destruct内没有清除datamember的行为,对吧
作者: LPH66 (-6.2598534e+18f)   2021-04-02 13:02:00
或者应该反过来说, compiler 就是没偷做什么才会还能让你偷偷回去挖里面原来放了些什么东西ie.这里没照规矩做事的反而是程式去存取已经结束生命的变量
作者: unmolk (UJ)   2021-04-03 03:43:00
在这串学到许多+1 谢谢板上各位大大!
作者: steve1012 (steve)   2021-04-06 03:11:00
特别去清掉会造成performance hit 没什么必要

Links booklink

Contact Us: admin [ a t ] ucptt.com