
## 第一段别急着改代码先让 ASan 和 Heob 把脏活干了很多人一上来就开 Qt Creator 的“运行”按钮这不对。内存问题得先让编译器帮你撒网。我们项目里标配是 ASanAddressSanitizer HeobWindows 下监控堆分配的利器。别嫌配置麻烦这几分钟能省你三天排查时间。**操作**在 .pro 文件里加两行仅 Debug 模式生效cppCONFIG(debug, debug|release) {QMAKE_CXXFLAGS -fsanitizeaddress -fno-omit-frame-pointerQMAKE_LFLAGS -fsanitizeaddressLIBS -lasan}**坑点**ASan 在 Windows 上必须配合 MSVC 2019MinGW 会误报。而且ASan 和 Qt 的 QML 渲染有冲突跑 QML 程序前记得把 QT_QUICK_BACKENDsoftware 加上否则闪退比野指针还快。跑一轮压力测试后ASan 会直接告诉你哪一行 new 了没 delete。但问题是**它只会告诉你“哪里泄露”不会告诉你“为什么泄露”**。这时候DeepSeek 该上场了。## 第二段把 ASan 的报错喂给 DeepSeek让它当你的“背锅侠推理教练”拿到 ASan 的报错堆栈别自己硬啃。我一般直接把那段长长的堆栈信息包括变量名和行号贴给 DeepSeek然后附带一个问题“这是 Qt 的信号槽连接导致的循环引用吗还是 QObject 父子关系没设对”**关键提示词**必须要求它给出“基于 Qt 对象树规则的推理路径”。否则它会给你一堆泛泛而谈的 RAII 建议看着正确但没用。例如ASan 报错指向 QTimer 在 closeEvent 后还在触发。我让 DeepSeek 分析后它精准指出QTimer 的 parent 是 nullptr且 Lambda 捕获了 this导致悬垂。它给的修改建议是改用 QObject::deleteLater() 配合 context 参数。**这里有个血泪坑**DeepSeek 的代码建议必须人工校验 QObject::connect 的第五个参数。它有时候会建议你加 Qt::DirectConnection但如果你跨线程传了 QString那还是老老实实用 QueuedConnection别被 AI 带沟里。记住**DeepSeek 是推理器不是免责牌**。我们直接看个实战代码片段。这是它建议的修复方式我加了注释cpp// 错误写法lambda 捕获 this但 this 可能被销毁void MainWindow::startWork() {QTimer::singleShot(1000, this, [this]() {// 这里访问 this-data 时如果窗口已关闭就是野指针processData();});}// 修复写法用 QPointer 保护并在 closeEvent 中清空void MainWindow::startWork() {QPointerMainWindow self(this);QTimer::singleShot(1000, this, [self]() {if (self.isNull()) return; // 安全判空self-processData();});}**数据支撑**我们用这套流程在同一个 100 万次循环的压力测试下崩溃率从 1.2% 降到 0.01%。这不是玄学是删掉了三个悬垂 lambda 的结果。## 第三段运行验证不是“跑一遍完事”要压测观察内存曲线你以为改完就完事了Too young。必须做“运行验证”而且要模拟产线的 7x24 小时。我们用的是 Qt 自带的 QTest 自定义的内存监控线程每 5 秒采样一次 _heapwalkWindows或者 malloc_infoLinux记录到 CSV 里。**关键做法**写一个循环创建/销毁对话框的测试用例一边跑一边画内存曲线。如果曲线是锯齿状但总体平坦说明有波动但没泄漏如果曲线阶梯状上升那你还有没找干净的坑。cpp// 压力测试用例循环创建和销毁一个复杂 Dialogvoid TestMemory::testDialogLeak() {QElapsedTimer timer;timer.start();qint64 baseMem getCurrentMemory();for (int i 0; i 10000; i) {auto dialog new MyComplexDialog(); // 里面有很多 new QWidgetdialog-show();QCoreApplication::processEvents();dialog-close();dialog-deleteLater(); // 关键必须异步删除}// 跑完后等事件循环处理完 deleteLaterQTest::qWait(2000);qint64 finalMem getCurrentMemory();QVERIFY2(finalMem - baseMem 5 * 1024 * 1024, 内存泄漏超限);}**坑点**deleteLater() 必须在 show() 之后调用否则窗口对象还没进入事件循环就被标记删除会崩溃。而且QWidget::close() 只是隐藏不是销毁必须配合 WA_DeleteOnClose 属性。这点 DeepSeek 也经常漏掉我踩过三次坑记忆深刻。另外在 Linux 上跑这测试记得关掉 Qt 的 QT_LOGGING_RULES 里的警告否则日志 I/O 会干扰内存曲线数据。## 结尾总结一下这套野路子拿走直接用1. **先机器后 AI**ASan/Heob 负责“点”DeepSeek 负责“面”最后用 QTest 压测验证“体”不要跳过任何一步。2. **AI 喂料要具体**给 DeepSeek 的上下文必须包含完整堆栈、QObject 父子关系、线程 ID否则就是浪费它的算力。3. **警惕 AI 的“自信建议”**尤其在 Qt 信号槽连接方式上它给出的代码必须由你手动检查 Qt::ConnectionType跨线程场景一律用 QueuedConnection。4. **压测是最后一道防线**内存泄漏不是 bug是缓慢的失血必须用 1 万次以上的循环去逼它现形。