C_and_CPP 板


LINE

开发平台(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的变数还能存取到他的数值呢? 请版上先进指教, 谢谢。 --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.163.153.38 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1617285280.A.419.html
1F:→ nh60211as: 你运气好(不好) 04/01 21:57
2F:推 LPH66: 就只是单纯当时分给他的位置还没人来而已 04/01 21:57
3F:→ Lipraxde: 写出 UB 就是爽,一直写 UB 一直爽 04/01 21:58
undefined behavior? ※ 编辑: Keitaro (1.163.153.38 台湾), 04/01/2021 22:01:37
4F:→ Lipraxde: 是 undefined behavior 没错,不过你这个例子,compile 04/01 22:37
5F:→ Lipraxde: r 应该会报 warning / error 吧? 04/01 22:37
warning我没仔细看明天确认一下, error当然是没有的 不然就无法执行了
6F:推 ando5566: 并没有free掉 ,stack pointer 和base pointer回到上一 04/01 22:56
7F:→ ando5566: 个function的状态,你在callee之後宣蹷@个大的阵列即 04/01 22:56
8F:→ ando5566: 可把stack memory洗掉。 04/01 22:56
这样的话 那我想再请教一下关於解构式的意义了 我以为会跑解构式就已经是把这个物件准备从memory中移除了耶 以new的方式来看 用上面相同的程式码 我如果写 StructB *pB = new StructB; delete pB; 在delete pB之後在VC里面debug看m_nB的数值会是???? 表示无法存取的状态 请问静态宣告local变数跟动态new变数 在free跑完解构式的差异是? ※ 编辑: Keitaro (1.163.153.38 台湾), 04/01/2021 23:32:52
9F:→ Lipraxde: 差别是放在 stack 上还说 heap 上 04/01 23:57
我懂了 您的意思是说在stack上的需要等这个stack被洗掉才会真正release是吗?
10F:→ Lipraxde: 如果有 address sanitizer 可以用的话开起来应该也可以 04/01 23:57
11F:→ Lipraxde: 在执行时跳出错误 04/01 23:57
感恩 来去学一下 谢谢 ※ 编辑: Keitaro (1.163.153.38 台湾), 04/02/2021 00:14:47
12F:→ sarafciel: 严格说起来是你的rsp/rbp改掉的时候就算release了 04/02 00:19
13F:→ sarafciel: 只是release不代表你的local variable值一定会改变 04/02 00:21
我想您的意思应该是说当rsp/rbp改掉的时机是指 local variable解构式跑完->stack回到上一层 这个阶段 但这个stack在记忆体的位置并没有被free掉 只是rsp/rbp改成上一层stack而已 所以我去存取这个local variable还能存取到他的数值 如果我想法是正确的 是否我改成这样 void foo2() // 不做任何事 {} int main() { StractA stA; foo(stA); foo2(); return 0; } 是否这样foo()的stack就会被洗掉了? stA.m_pB->m_nB 再也无法存取? ※ 编辑: Keitaro (1.163.153.38 台湾), 04/02/2021 00:37:31
14F:推 b0920075: 有没有洗掉不是很重要,就算他没被洗掉你也不应该去用 04/02 00:33
15F:→ b0920075: ,谁知道等下还会不会留着 04/02 00:33
我了解 只是我想知道compiler到底是偷做了甚麽事颠覆了我对变数lifecycle的认知这样 我当然是不敢这样去用上一个stack的local variable的. ※ 编辑: Keitaro (1.163.153.38 台湾), 04/02/2021 00:44:06
16F:→ sarafciel: 你对free跟lifecycle消灭的定义是什麽呢? 04/02 01:52
17F:→ sarafciel: 是执行期当你access这块记忆体时 程式应该要报错吗? 04/02 01:53
是的 我以为lifecycle结束就跑解构式 已经跑过解构式的物件 在记忆体上就已经被删除 既然被删除就应该是无法存取了 我一直以为是这样
18F:→ Lipraxde: Compiler 没偷做什麽,顶多说是偷懒没把 stack 刷掉 04/02 02:31
19F:→ a1u1usul3: 为什麽删除的档案还有机会找回来?因为刚好没被洗掉。 04/02 04:14
20F:→ a1u1usul3: 为什麽上一个function里面local variable还在?因为刚 04/02 04:14
21F:→ a1u1usul3: 好没被洗掉 04/02 04:14
22F:→ a1u1usul3: compiler没有偷做什麽,他只是不再使用这个地方而已。 04/02 04:17
23F:→ a1u1usul3: 既然已经不再使用这里也就不用特地清成0了 04/02 04:17
原来如此 所以读到那个1真的只是运气好而已
24F:推 ando5566: 先执行destructor ,再离开当下function (做stk /bsp re 04/02 08:17
25F:→ ando5566: store) ,最後pop pc+1 与jump ;destruct内没有清除data 04/02 08:17
26F:→ ando5566: member的行为,对吧 04/02 08:17
27F:推 LPH66: 或者应该反过来说, compiler 就是没偷做什麽才会还能让你 04/02 13:02
28F:→ LPH66: 偷偷回去挖里面原来放了些什麽东西 04/02 13:03
29F:→ LPH66: ie.这里没照规矩做事的反而是程式去存取已经结束生命的变数 04/02 13:04
了解了 非常感谢以上各位的说明 让小弟我又学到不少 谢谢! ※ 编辑: Keitaro (1.163.153.38 台湾), 04/02/2021 13:45:36
30F:推 unmolk: 在这串学到许多+1 谢谢板上各位大大! 04/03 03:43
31F:推 steve1012: 特别去清掉会造成performance hit 没甚麽必要 04/06 03:11







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:WOW站内搜寻

TOP