二叉搜索树节点删除代码疑问:访问已删除节点为何仍能得到正确结果?
二叉搜索树节点删除代码疑问:访问已删除节点为何仍能得到正确结果?
你这个问题问得特别到位,很多刚摸C内存管理的同学都会遇到这种“明明写错了却能跑通”的诡异情况,其实核心原因是C里的未定义行为在作祟,咱们一步步拆解:
首先说代码1,这是完全正确的写法:
Node* temp = root->right; delete root; return temp;
你先把要返回的右子节点地址存到temp里,再释放root指向的内存,最后返回temp——整个过程没有访问已释放的内存,逻辑严谨,完全符合内存安全规范。
再看代码2,这其实是错误的写法,只是碰巧“蒙对”了结果:
Node* temp = root; delete temp; return root->right;
这里你删除temp后,root就变成了一个悬垂指针(指向已经被操作系统回收的内存),这时候去访问root->right属于访问已释放内存,在C++里这是明确的未定义行为。
那为什么它还能返回正确值呢?
原因很简单:操作系统回收内存后,并不会立刻把这块内存的内容清零或者覆盖。短时间内,原来存在这块内存里的right指针值可能还没被改动,所以你访问的时候刚好拿到了原来的正确地址。但这纯粹是运气,不是代码逻辑正确!
这种代码的风险极大:换个编译器、换个运行环境,或者程序运行时内存紧张,那块被释放的内存很快被其他数据覆盖,这时候再访问root->right要么得到错误值,要么直接触发段错误导致程序崩溃。
总结一下:代码1是安全可靠的正确写法,代码2只是碰巧“工作”了,本质上是错误的,绝对不能依赖这种未定义行为来写代码。
备注:内容来源于stack exchange,提问作者Umang Garg
相关产品推荐
相关产品推荐

