删除指向同一块内存的两个指针之一后出现异常行为的相关疑问
1. 释放内存后操作同指向的另一个指针没有报错的原因
C++标准将「访问已通过delete释放的堆内存」定义为未定义行为,没有强制要求这类操作必须抛出错误或者触发崩溃。delete释放内存的本质是将对应内存块的使用权交还给堆分配器,分配器仅会标记该内存块为空闲可复用状态,不会立刻擦除内存内容、也不会直接禁止程序访问该地址。只要这块内存还没有被分配给新的内存申请,对它的读写操作大概率不会触发操作系统的内存访问异常,你观测到的输出垃圾值、可以正常写入10都属于未定义行为的典型表现,这类运行结果完全不可靠,一旦该内存块被分配给其他变量,你的写入操作会直接破坏其他逻辑的运行,属于严重的内存安全错误。
2. delete后指针存储的地址发生变化的原因
该现象确实和编译器及编译配置有关:
C标准明确规定delete表达式本身不会修改传入的指针变量的取值,默认情况下delete执行后指针会保留原来的内存地址,成为野指针。
但目前主流编译器的调试编译模式(例如MSVC的Debug配置、GCC开启地址消毒器等安全检查选项时)会增加额外的安全逻辑,在delete执行后自动将被释放的指针变量设置为一个无效的哨兵地址,目的是帮助开发者更快识别野指针访问问题,这属于编译器的扩展安全特性,不属于C标准的强制要求。如果切换到Release模式编译并关闭所有调试安全选项,你会看到delete执行后ptr仍然保留原来的00CE4ED0地址。
需要注意的是,编译器只会修改你直接传给delete的指针变量的取值,不会自动更新所有指向同一块内存的其他指针,这也是悬空指针问题难以排查的核心原因之一。
内容的提问来源于stack exchange,提问作者Yura Pazyn
相关产品推荐
相关产品推荐

