delete和free不能混用:new分配的必须用delete/delete[]释放,malloc分配的必须用free释放;否则导致未定义行为,包括内存泄漏、堆损坏或崩溃。

delete 和 free 不能混用,否则必然未定义行为
这是最硬的铁律:用 new 分配的内存必须用 delete(或 delete[])释放;用 malloc 分配的必须用 free。两者底层分配器可能不同,元数据格式不兼容,强行交叉调用轻则内存泄漏,重则堆损坏、程序崩溃——哪怕对象是 int 这种内置类型也一样。
delete 会调析构函数,free 完全不关心对象生命周期
这是语义鸿沟的核心。当你写 delete ptr,编译器生成的代码一定包含两步:先调用 ptr 所指对象的析构函数,再调用 operator delete 归还内存。而 free(ptr) 只做一件事:把这块原始字节交还给堆管理器,不管里面有没有 std::string、文件描述符或自定义资源。
- 如果你用
malloc分配一个class Widget { std::vector,然后v; }; free它:v 的析构函数永远不会执行,内部缓冲区永久泄漏 - 如果你用
new分配,却用free释放:析构函数跳过,但operator delete没被调,内存可能没真正归还,或触发断言失败
delete 是运算符,free 是函数,底层行为和错误处理机制完全不同
delete 是 C++ 语言级运算符,参与编译期类型检查、异常传播和重载机制;free 是 C 标准库函数,只认地址,不认类型,也不抛异常。
-
delete nullptr是安全的,标准明确允许;free(nullptr)同样安全,但这是两个独立约定,不可推导 -
new失败默认抛std::bad_alloc;malloc失败返回nullptr,必须手动判空 - 你可以重载
operator new和operator delete来定制分配策略;free无法重载,只能替换整个 malloc 实现(如 jemalloc)
数组场景下 delete[] 和 free 的错配尤其危险
用 new[] 分配的数组,必须用 delete[] 释放。若误用 free,不仅跳过每个元素的析构,还可能因元数据读取错误导致越界写或崩溃。
-
int* p = new int[100]; delete[] p;→ 正确,析构零个(内置类型无析构),清理数组元数据 -
int* p = new int[100]; free(p);→ 错误,绕过operator delete[],元数据结构可能被破坏 -
Widget* w = new Widget[10]; free(w);→ 更糟,10 个Widget的析构函数全跳过,内部资源全部泄漏
实际工程里,这类错配往往在混合 C/C++ 接口时发生,比如 C 接口返回 malloc 内存,C++ 层误当 new 结果来 delete——这种 bug 不一定立刻暴露,但会在压力测试或长期运行后突然崩掉。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











