C++执行delete[] p释放动态数组后值仍存在是什么原因?
核心结论
你遇到的现象不是代码编写逻辑遗漏,是访问已释放内存触发的未定义行为,和VSCode、所用插件的运行环境没有本质关系。
原理说明
delete[]的实际作用只有两个:- 对数组内每个元素调用对应析构函数,
int是基础内置类型,没有自定义析构逻辑,这一步不会产生任何操作 - 将指针指向的堆内存块标记为“空闲可复用”,交还给堆内存管理器
整个释放过程没有任何规则要求强制擦除内存中存储的旧数据,也不会自动修改原指针本身的指向。
- 对数组内每个元素调用对应析构函数,
- 执行
delete[] p后,p就成为了悬空指针,此时读写p[0]、p[1]属于C++标准明确规定的未定义行为:标准不对这类操作的结果做任何保证,你可能读到旧值、可能读到随机脏数据、可能程序直接崩溃,任何运行结果都属于“符合标准”的表现,不存在“释放后值一定会改变”的规则。 - 你当前运行能稳定读到10、20的原值,只是因为程序释放内存后没有立刻对这块内存做新的写入操作,操作系统也没有回收对应的内存页,旧数据暂时残存在内存地址上而已。这个结果完全不稳定:换编译优化等级、增加几行其他内存分配的代码、换不同的编译器/操作系统,运行结果都可能发生变化,绝不能在实际代码中依赖这种表现。
- 你当前用CodeRunner默认的编译配置通常是无优化的Debug模式,默认内存分配器不会在释放内存时主动擦写内容,所以很容易观察到“释放后还能读旧值”的现象;如果开启地址消毒器(ASAN)这类内存检测工具编译,访问已释放内存会直接抛出明确的内存错误,不会给你读到旧值的机会。
编码建议
释放堆内存后请第一时间将指针置为
nullptr,从根源避免意外访问悬空指针的问题。
对应代码片段参考:
delete[] p; p = nullptr;
置空后如果再误访问p[0],绝大多数运行环境会直接触发内存访问错误崩溃,可以快速定位问题,避免隐蔽的内存bug。
内容的提问来源于stack exchange,提问作者tall_call_9129
相关产品推荐
相关产品推荐

