Valgrind报“Mismatched free()/delete/delete[]”表明new/new[]与delete/delete[]混用,属未定义行为:new[]必须配delete[],new配delete,malloc/free自成体系,混用将导致析构失败或内存损坏。

看到 Mismatched free() 就该查 new/delete 对应关系
Valgrind 报 Mismatched free() / delete / delete[],本质是 C++ 中动态内存的分配与释放方式不匹配。这不是“可能出错”,而是**未定义行为(UB)**,程序可能暂时跑通,但随时崩溃或静默损坏数据。核心原则只有一条:用 new 分配的,必须用 delete 释放;用 new[] 分配的,必须用 delete[] 释放;malloc 和 free 是另一套,不能混。
new[] 配 delete 是最常见错误源头
Valgrind 错误栈里如果出现类似这样的调用链:
1: operator new[](unsigned long) in ...<br>2: MainWindow::MainWindow(QWidget*) in mainwindow.cpp:13<br>...<br>1: operator delete(void*) in ...<br>2: MainWindow::MainWindow(QWidget*) in mainwindow.cpp:14
说明你在第 13 行用了 new[](比如 int* p = new int[10];),却在第 14 行写了 delete p; —— 少了方括号。这种写法在多数编译器下不会编译报错,但会触发 Valgrind 的 Mismatched free() 警告,并且实际析构行为不可靠(尤其对象类型有非平凡析构函数时)。
- ✅ 正确写法:
int* p = new int[10]; ... delete[] p; - ❌ 错误写法:
int* p = new int[10]; ... delete p;(Valgrind 必报) - ⚠️ 特别注意:
std::vector、QString等容器内部也用new[],但你绝不能直接对它们的.data()或内部指针调用delete[]—— 容器自己管理内存
Qt 场景下容易忽略的隐式 new[] 陷阱
Qt 的某些 API 表面看是“普通指针”,实则背后调用了 new[]。典型如 QByteArray::data() 返回的指针不能被手动释放;更隐蔽的是自定义类成员中使用了 new[],但在析构函数里漏写 []。
- 检查所有自定义构造函数里有没有
new[],再逐个核对对应析构函数是否用了delete[] - Qt 的
qMalloc/qFree是malloc/free的封装,和new/delete不兼容 —— 别混用 - 如果用了
QScopedPointer或QSharedPointer,确保模板参数正确:对数组要用QScopedPointer,否则默认用> delete而非delete[]
为什么加 -g -O0 编译很重要
Valgrind 报错行号不准?大概率是你没用调试信息编译。没有 -g,它只能定位到汇编层级;开了优化(如 -O2),代码重排会让 new[] 和 delete 看似不在同一逻辑位置,误导判断。
- 务必用
g++ -g -O0 -Wall重新编译待测程序 - 运行命令推荐:
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --track-origins=yes ./your_program,其中--track-origins=yes对定位未初始化值有用,但对Mismatched free不是必需,可省略以加快速度 - 别依赖
--leak-check=summary—— 它会掩盖真正的问题根源,full才能看到分配/释放的完整堆栈
改完之后 Valgrind 不再报 Mismatched free,不代表内存就安全了——它只是把最危险的 UB 消除了。后续还得看 definitely lost 和 possibly lost 是否归零,那才是真正的泄漏闭环。











