1. 安装Valgrind
sudo apt-get install valgrind
2.编译
确保你的Qt项目是以调试模式编译的,这样Valgrind可以提供更详细的信息。在Qt Creator中,你可以选择Debug
构建配置进行编译。
3.运行Valgrind
valgrind --leak-check=full ./your-application
--leak-check=full
选项指示Valgrind进行详细的内存泄漏检查。
--show-reachable=yes
:显示仍然可达的内存块。
--track-origins=yes
:追踪未初始化内存的来源,帮助识别问题的根源。
————————————————./your-application
为你的Qt应用程序的可执行文件路径
4.查看报告
Valgrind将运行你的应用程序,并输出内存泄漏的详细报告到终端。报告中包括泄漏的内存块、泄漏的大小、以及可能导致泄漏的代码位置。
5.根据Valgrind报告中提供的信息,定位代码中可能导致内存泄漏的地方,进行修复
确保每个new
分配的内存都有对应的delete
。
使用Qt的父子对象机制自动管理内存。
确保在容器中删除不再需要的对象。
6.如何读取Valgrind生成的输出
==1234== Memcheck, a memory error detector
==1234== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1234== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1234== Command: ./yourapp
==1234==
==1234== HEAP SUMMARY:
==1234== in use at exit: 56 bytes in 2 blocks
==1234== total heap usage: 10 allocs, 8 frees, 1,048 bytes allocated
==1234==
==1234== 56 bytes in 1 blocks are definitely lost in loss record 1 of 1
==1234== at 0x4C2D1B4: malloc (vg_replace_malloc.c:309)
==1234== by 0x4011D2: main (main.cpp:10)
==1234==
==1234== LEAK SUMMARY:
==1234== definitely lost: 56 bytes in 1 blocks
==1234== indirectly lost: 0 bytes in 0 blocks
==1234== possibly lost: 0 bytes in 0 blocks
==1234== still reachable: 0 bytes in 0 blocks
==1234== suppressed: 0 bytes in 0 blocks
==1234==
==1234== For counts of detected and suppressed errors, rerun with: -v
==1234== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
关键部分的解释
HEAP SUMMARY(堆内存总结):
- in use at exit: 程序退出时,仍然占用的内存量。这里显示为56字节。
- total heap usage: 堆内存的总使用情况,包括分配和释放的统计信息。
LEAK SUMMARY(泄漏总结):
- definitely lost: 确定的内存泄漏。显示为56字节。
- indirectly lost: 间接泄漏的内存。这是因为某些对象或数据结构被遗忘,导致它们无法被释放。
- possibly lost: 可能泄漏的内存。Valgrind不能确定,但有可能丢失。
- still reachable: 仍然可达的内存。内存尚未释放,但可以通过有效的指针访问。通常这不是泄漏,但可能表示内存管理不当。
- suppressed: 被抑制的内存问题数量。
详细错误记录:
- 56 bytes in 1 blocks are definitely lost in loss record 1 of 1:详细说明了泄漏的内存块的大小和位置。
- at 0x4C2D1B4: malloc (vg_replace_malloc.c:309):显示内存泄漏的具体位置,包括函数名称和文件行号。
- by 0x4011D2: main (main.cpp:10):显示导致内存泄漏的代码行。
查找错误记录:查看“LEAK SUMMARY”部分,找出“definitely lost”或其他错误信息的具体记录。
定位源头:
- 在错误记录中,找到类似“at 0x...”的地址,这表明出错的地方。
- 使用该地址查找源代码,通常报告会附带文件名和行号,如“main.cpp:10”。
分析调用栈:
- 查阅“LEAK SUMMARY”中的调用栈信息,找出导致错误的函数调用链。
- 调用栈的上层通常显示了内存分配的位置,而下层显示了最终导致问题的地方。
结合源代码:
- 在源代码中打开报告中提到的文件和行号,检查内存分配和释放逻辑。
- 确保所有分配的内存都在合适的地方被释放。