不能用 delete[] 释放 malloc 分配的内存,这是未定义行为;delete[] 会越界读取不存在的数组长度信息并可能错误调用析构函数,导致崩溃或堆损坏。
![c++中delete[]释放malloc申请的数组会怎样](https://img.php.cn/upload/article/001/221/864/179014644147070.png)
delete[] 释放 malloc 分配的数组:直接崩溃或未定义行为
不能用 delete[] 释放 malloc 申请的内存,哪怕它是个数组。这不是“可能出错”,而是标准明确禁止的未定义行为(UB)。编译器不保证任何结果——程序可能看似正常退出,也可能在释放时立即段错误、踩内存、破坏堆结构,甚至延迟到后续某次 malloc 或 free 才崩。
为什么 delete[] 对 malloc 数组特别危险
delete[] 假设内存由 new[] 分配,会尝试读取隐藏在用户数据前的“数组长度 cookie”(通常是 4 或 8 字节),再调用每个元素的析构函数(对 POD 类型虽无实际动作,但指针偏移逻辑仍存在)。而 malloc 返回的地址就是用户数据起始处,前面没有 cookie,delete[] 会越界读取随机内存,导致:
- 读取非法地址 → SIGSEGV 崩溃
- 读到垃圾值当作数组长度 → 错误循环调用析构函数(若类型非 POD)
- 内部堆管理器元数据被意外修改 → 后续
free或malloc失败
常见误判场景:int 数组“看起来能跑通”
有人测试过类似代码:int* p = (int*)malloc(10 * sizeof(int)); delete[] p;,发现没报错。这纯属侥幸 —— 因为 int 是 POD 类型,不调用析构函数,且某些 libc 实现(如 glibc 的 malloc)在 debug 模式下未校验 cookie,掩盖了问题。但一旦:
- 换成
std::string*或自定义类数组,delete[]会尝试调用 10 次析构函数,而对象根本没被new[]构造过 → 崩溃或静默损坏 - 换到 ASan(AddressSanitizer)或 UBSan 下运行 → 直接报
heap-use-after-free或invalid operator delete[] - 切换编译器或 libc 版本(如 musl)→ 立即失败
正确配对永远只有一条铁律
内存分配和释放必须严格按源头匹配:
立即学习“C++免费学习笔记(深入)”;
-
malloc/calloc/realloc→ 必须用free -
new→ 必须用delete -
new[]→ 必须用delete[]
混用的后果不是“性能差一点”,而是彻底脱离标准约束。哪怕你 100% 确定只放 int,只要用了 malloc,就绝不能碰 delete 或 delete[] —— 这个边界一旦模糊,整个内存生命周期就不可推演。


















