free只能释放malloc/calloc/realloc分配的堆内存,对new/new[]、栈/全局内存或字符串字面量调用会导致未定义行为;应优先使用RAII(如unique_ptr配自定义deleter)替代裸指针+free。

free 只能释放 malloc/calloc/realloc 分配的内存
直接对 new 或 new[] 分配的指针调用 free 是未定义行为,程序可能崩溃或静默损坏堆。C++ 的 new 调用构造函数、delete 调用析构函数,而 free 完全不处理这些逻辑。
常见错误现象:double free、heap corruption、segmentation fault,尤其在混合使用 malloc 和 delete 时极易触发。
- 只对
malloc、calloc、realloc返回的指针用free - 确保传入
free的指针是原始分配地址(不能是偏移后的指针) - 释放后立即将指针设为
nullptr,避免重复释放
free(nullptr) 是安全的,但 free(已释放指针) 不是
free(nullptr) 标准规定必须无副作用,可放心调用;但若对已 free 过的指针再次调用,属于未定义行为——有些 libc 实现会报 double free or corruption,有些则直接崩溃。
典型误用场景:多个作用域共享同一指针、异常路径遗漏释放、智能指针与裸指针混用。
立即学习“C++免费学习笔记(深入)”;
- 每次
free后手动置为nullptr:free(p); p = nullptr; - 不要依赖“记得没释放过”这种人工判断,尤其在分支或循环中
- 调试时可用
MALLOC_CHECK_=3环境变量(glibc)捕获部分 double-free
free 无法释放栈内存或全局内存
free 只管理堆上由 malloc 系列函数分配的内存块。对栈变量地址(如 int x; free(&x);)、全局数组、字符串字面量(char *s = "hello"; free(s);)调用 free 会立即导致段错误。
这类错误往往在代码重构时引入:比如把原本栈分配的结构体改成指针传递,却忘了改内存管理方式。
- 检查指针来源:是否来自
malloc?是否被const_cast转换过?是否指向数组首地址而非 malloc 块? - 字符串字面量地址不可释放,需复制到堆上才能用
free - 用 AddressSanitizer(
-fsanitize=address)能直接报出此类非法释放
C++ 中更推荐用 RAII 而非手动 free
裸指针 + free 在 C++ 里属于低级且易错的模式。现代 C++ 应优先用 std::vector、std::string、std::unique_ptr(配合自定义 deleter 使用 free)等 RAII 容器。
如果必须对接 C API(如 libcurl、OpenSSL),才需要显式 free;此时建议封装成 RAII 类型:
struct c_string_deleter {
void operator()(char* p) const { free(p); }
};
std::unique_ptr<char, c_string_deleter> p{static_cast<char*>(malloc(100))};- 避免在普通业务逻辑中出现
malloc/free - 若用
std::unique_ptr管理 C 风格内存,务必指定正确 deleter - 注意
free不检查指针有效性,RAII 封装能天然规避空指针/重复释放问题
实际写 C++ 时,真正需要写 free 的地方比想象中少得多——多数时候是掉进了 C 风格惯性思维,或者没看清所用库的内存所有权契约。


















