[QT编程系列-43]: Windows + QT软件内存泄露的检测方法
目录
一、如何查找Windows程序是否有内存泄露
二、如何定位Windows程序内存泄露的原因
二、Windows环境下内存监控工具的使用
2.1 内存监测工具 - Valgrind
2.2.1 Valgrind for Linux
2.2.2 Valgrind for Windows
2.2 内存监测工具 - Dr. Memory
2.2.1 特点
2.2.2 安装和操作步骤
2.3 内存监测工具 - Visual Leak Detector
2.3.1 简介
2.3.2 简介 Vsual Leak Detector(VLD)检测内存泄露的步骤
2.4 内存监测工具 - WinDbg
2.4.1 简介
2.4.2 安装和操作步骤
2.5 Windows进程内存监控工具
2.6 Windowx线程内存 监控工具
2.7 API函数获取线程级内存使用情况
2.8 Windows性能监控
三、QT程序如何定位内存泄露
3.1 常见工具总结
3.2 qdebug辅助内存泄露定位
3.3 qml profiler 辅助性能监控
3.3.1 QML Profiler 提供了以下主要功能:
3.3.2 要使用 QML Profiler,您可以按照以下步骤操作:
精华:
一、如何查找Windows程序是否有内存泄露
要查找Windows程序的内存泄漏,可以采取以下方法:
-
重现测试:尝试通过多次重现测试来调查内存泄漏的可能性。观察程序在特定操作或场景下内存占用的变化情况,看是否有持续增长的趋势。
-
使用内存监测工具:使用专业的内存监测工具,如Valgrind、Visual Leak Detector、WinDbg等,可以帮助检测内存泄漏问题。这些工具可以跟踪程序的内存分配和释放情况,并标识出可能的泄漏点。
-
使用性能监测工具:使用性能监测工具(如Windows自带的性能监视器)来检查程序的内存使用情况。观察随时间变化的内存占用情况,如果内存占用不断增长且没有回收,可能存在内存泄漏。
-
使用内存剖析器(Profiler):内存剖析器可以跟踪程序的内存分配和释放过程,并提供详细的内存使用情况报告,帮助定位内存泄漏。一些集成开发环境(如Visual Studio)或第三方工具都提供内存剖析功能。
-
手动检查:仔细检查程序中使用的各种数据结构、对象、缓存等是否正确释放。确保在不再使用时,显式释放相关的内存。
-
分析代码:仔细分析程序的源代码,特别关注内存分配和释放的位置。检查是否存在没有合理释放内存的情况,例如忘记调用 delete 或 free,或者在循环中反复分配内存而未释放。
-
使用自动化检查工具:一些自动化工具可帮助检查内存泄漏。例如,编写自动化测试用例以模拟程序的运行并定期检查内存使用情况。
需要注意的是,内存泄漏问题可能复杂且难以定位。它可能由于多种因素引起,因此需要耐心和仔细地进行调查和分析。结合上述方法和工具,您可以逐步缩小问题范围,并找到内存泄漏的根源。
二、如何定位Windows程序内存泄露的原因
要定位Windows程序的内存泄漏原因,可以采取以下方法:
-
使用内存监测工具:使用专业的内存监测工具,如Valgrind、Visual Leak Detector、WinDbg等,可以实时跟踪程序的内存分配和释放情况。这些工具可以捕获内存泄漏的堆栈信息和泄漏的对象,并帮助定位具体的泄漏点。
-
分析泄漏报告:通过内存监测工具生成的泄漏报告,可以获取泄漏对象的详细信息。检查泄漏对象的堆栈跟踪,了解泄漏发生的上下文,以帮助定位具体的泄漏原因。
-
使用内存剖析器(Profiler):内存剖析器可以对程序的内存使用进行分析,并提供详细的内存分配和释放信息。通过分析内存剖析器的报告,可以查看程序中哪些对象占用了大量的内存,以及释放内存的频率如何。这有助于找到可能导致泄漏的问题代码。
-
检查未释放的内存:通过仔细检查代码,查找未释放的内存情况。特别关注释放内存的位置,确保每个内存分配都能够正确释放。
-
研究引起内存泄漏的模式:检查内存泄漏发生的模式,例如在特定的代码分支、循环或特定情况下。这可能有助于定位泄漏发生的原因。
-
运行压力测试:通过模拟程序在稳定和高负载的环境下运行,可以观察内存占用情况是否持续增长。如果内存占用持续增长并且不释放,可能存在内存泄漏。在此基础上,观察程序的行为和内存使用情况,以确定可能导致泄漏的操作。
-
排除其他因素:除了内存泄漏外,其他因素也可能导致内存占用增加,如内存碎片化、缓存未清理等。因此,在排查内存泄漏之前,先排除这些可能的因素。
-
阅读文档和调试信息:查阅程序的文档、日志和调试信息,以了解是否存在已知的内存泄漏问题和解决方案。
需要注意的是,内存泄漏问题可能由多个因素引起,并且可能涉及复杂的程序逻辑。因此,要定位和解决内存泄漏问题需要耐心和谨慎分析。使用以上方法和工具,可以逐步缩小问题范围,并找到内存泄漏的原因。
二、Windows环境下内存监控工具的使用
2.1 内存监测工具 - Valgrind
2.2.1 Valgrind for Linux
valgrind 是一个强大的开源内存监测工具,用于检测内存泄漏、内存错误和性能问题。
Valgrind 主要用于 Linux 和类 Unix 系统,它提供了多个工具,其中最常用的是 Memcheck。
使用 Valgrind 的 Memcheck 工具,您可以在运行程序时进行内存分析,并捕获以下问题:
-
内存泄漏:Memcheck 可以跟踪程序中所有的内存分配和释放操作,并检查是否有内存未被正确释放,从而发现内存泄漏问题。
-
未初始化的内存访问:Memcheck 在访问未初始化的内存时会发出警告,帮助您发现潜在的错误。
-
重复释放和无效释放:Memcheck 可以检测到重复释放同一块内存或释放已经被释放的内存的情况。
-
读写越界:Memcheck 能够检测到数组和指针操作中的读写越界错误,帮助您找出可能导致程序崩溃或不可预料行为的问题。
-
内存管理错误:Memcheck 还可以检测到堆栈溢出、使用已经被释放的内存、多线程内存访问冲突等内存管理错误。
使用 Valgrind 和 Memcheck 工具可以提供非常详细的内存问题报告,包括泄漏点的堆栈跟踪、泄漏的内存大小等信息,这些信息有助于定位和解决内存问题。
请注意,Valgrind 可能会对程序的执行速度产生一定的影响,并且只能用于在类 Unix 系统上运行的程序。在使用 Valgrind 之前,建议备份好您的程序,并确保您的程序在测试环境中仍然具有正常的行为。
更多关于 Valgrind 和 Memcheck 的信息和用法,您可以参考 Valgrind 官方文档和相关资源。
2.2.2 Valgrind for Windows
Valgrind 不直接支持 Windows 操作系统。Valgrind 是一个专为类 Unix 系统设计的工具,其核心功能依赖于类 Unix 的内核功能,如内存管理和调试接口等。
然而,在 Windows 环境中,有一种称为 “Valgrind for Windows” 的工具,可以模拟 Valgrind 的功能。这个工具称为 “Dr. Memory”,它是一个基于 Valgrind 的内存检测工具,专门用于 Windows 系统。
Dr. Memory 提供了类似于 Valgrind 的内存检测功能,可以帮助检测内存泄漏、未初始化内存访问等问题。它提供了详细的报告,以指导您定位和解决内存问题。
2.2 内存监测工具 - Dr. Memory
2.2.1 特点
Dr. Memory 的主要特点包括:
-
内存检测功能:Dr. Memory 可以跟踪应用程序的内存分配和释放,并检测内存泄漏和无效内存访问。它能够发现未释放的内存、重复释放、释放已释放内存、读写越界等问题。
-
详细报告:Dr. Memory 会生成详细的报告,包括发现的问题、相关的堆栈跟踪和错误信息。这些报告可以帮助开发人员定位和修复内存错误。
-
容易集成:Dr. Memory 可以与各种开发环境和构建工具集成,方便在开发过程中进行内存错误检测。它支持命令行和图形界面两种使用方式。
-
支持多线程:Dr. Memory 能够在多线程应用程序中检测内存问题,并提供相关的线程调用堆栈信息,帮助跟踪和定位问题所在。
-
高效性能:Dr. Memory 使用了一些优化技术,以最小化对应用程序性能的影响,并减少内存使用。
Dr. Memory 是一个免费且开源的工具,您可以从其官方网站(https://drmemory.org/)下载并获取相关的文档和资源。在使用 Dr. Memory 进行内存错误检测时,请务必遵循官方的用法和建议,以获得最佳的结果。
2.2.2 安装和操作步骤
Dr. Memory 是一个能够帮助检测 Windows 系统上的内存泄漏问题的工具。
以下是使用 Dr. Memory 进行内存泄漏检测的基本步骤:
-
下载和安装:从 Dr. Memory 的官方网站(https://drmemory.org/)下载适用于 Windows 的安装程序,并按照指引进行安装。
-
配置环境变量:将 Dr. Memory 的可执行文件目录添加到系统的 PATH 环境变量中,以便能够在命令行中直接访问 Dr. Memory。
-
运行程序:使用 Dr. Memory 运行您要检测的程序。在命令行中,使用 drmemory.exe 命令后面跟上您要运行的程序的路径。例如:drmemory.exe your_program.exe。
-
分析报告:Dr. Memory 会在程序运行结束后生成一个报告文件。您可以在命令行中查看报告的路径,也可以手动在报告输出目录中找到相关报告文件。
-
查找泄漏点:打开报告文件,查找标记为 “LEAK SUMMARY” 的部分。这部分会列出检测到的内存泄漏情况,包括泄露对象的数量、大小和泄露的位置(堆栈跟踪信息)。通过分析堆栈跟踪信息,可以定位泄漏点的源头。
-
解决问题:根据泄漏点的堆栈跟踪信息,确定泄漏发生的原因,并在代码中进行相应的修复。可能需要释放未使用的内存或修改内存管理逻辑,以修复泄漏问题。
-
重新运行程序和重复检测:对修复后的程序再次使用 Dr. Memory 进行运行和检测,以验证是否成功解决了内存泄漏问题。
请注意,Dr. Memory 提供了详细的报告和堆栈跟踪信息,非常有助于定位和解决内存泄漏问题。同时,确保在进行内存泄漏检测时,使用真实且具有代表性的测试场景和数据,以更好地模拟实际运行环境和内存使用情况。
2.3 内存监测工具 - Visual Leak Detector
2.3.1 简介
Visual Leak Detector(VLD)是一个针对 Windows 平台的内存泄漏检测工具,特别是针对使用 Visual Studio 进行开发的应用程序。它可以帮助开发人员检测和定位应用程序中的内存泄漏问题。
以下是使用 Visual Leak Detector 进行内存泄漏检测的基本步骤:
-
下载和安装:从 Visual Leak Detector 的官方网站(https://vld.codeplex.com/)下载适用于您的 Visual Studio 版本的安装程序,并按照指引进行安装。
-
配置项目:打开您的 Visual Studio 项目,右键单击该项目,选择 “Properties”(属性)选项。在弹出的属性页中,选择 “Debugging”(调试)选项卡,然后将 “Debugger to launch”(要启动的调试器)设置为 “Native Only”(仅本机)。
-
引入头文件:在您的项目的源代码文件中包含 VLD 的头文件。通常情况下,只需在主文件(如 main.cpp)的开头引入以下代码:#include 。
-
构建和运行:重新构建您的项目,并以调试模式运行应用程序。VLD 将会在程序退出时自动检测内存泄漏,并在 Visual Studio 的输出窗口中显示相关的泄漏信息。
-
分析报告:查看 Visual Studio 输出窗口中的 VLD 泄漏信息,并根据提供的堆栈跟踪信息定位泄漏点。VLD 会列出每个泄漏的内存块的大小、地址和泄漏位置的堆栈跟踪信息。
-
解决问题:根据泄漏点的堆栈跟踪信息,确定泄漏发生的原因,并在代码中进行相应的修复。可能需要释放未使用的内存或修改内存管理逻辑,以修复泄漏问题。
请注意,Visual Leak Detector 可以帮助检测内存泄漏,但它会对性能产生一些影响。为了获得准确的泄漏信息,请确保在真实且具有代表性的测试场景和数据下运行应用程序。
2.3.2 简介 Vsual Leak Detector(VLD)检测内存泄露的步骤
Visual Leak Detector(VLD)是一个用于检测内存泄漏的工具,它可以帮助开发人员在 Windows 平台上使用 Visual Studio 进行应用程序开发时,找出内存泄漏问题。
下面是使用 Visual Leak Detector 检测内存泄漏的一般方法:
-
下载和安装:从 Visual Leak Detector 的官方网站(https://vld.codeplex.com/)下载适用于您的 Visual Studio 版本的安装程序,并按照指示进行安装。
-
配置项目:将 Visual Leak Detector 添加到您的项目中。在 Visual Studio 的项目属性页中,打开 “C/C++” 选项,然后在 “预处理器” 中添加 #define VLD_FORCE_ENABLE 宏定义。这将强制启用 VLD。
-
构建和运行:重新构建您的项目,并以调试模式运行应用程序。VLD 将自动在应用程序退出时检测内存泄漏。
-
分析报告:当应用程序退出后,在调试输出窗口中会显示 VLD 的检测报告。这些报告包含了内存泄漏的详细信息,如泄漏的内存块大小、地址和泄漏点的堆栈跟踪信息。
-
调试和解决问题:根据报告中的堆栈跟踪信息定位泄漏点,并在代码中进行相应的调试和修复。根据情况,可能需要手动释放未使用的内存或优化内存管理逻辑。
-
重复检测:对修复后的应用程序再次运行,并使用 VLD 进行内存泄漏检测,以确保问题已经解决。
请注意,Visual Leak Detector 是一个强大的工具,可以辅助内存泄漏问题的检测和修复。但它对应用程序性能有一定的影响,因此建议在进行生产环境部署之前移除或禁用 VLD。同时,为了获得准确的泄漏信息,请确保使用真实且具有代表性的测试场景和数据进行测试。
2.4 内存监测工具 - WinDbg
2.4.1 简介
WinDbg是Windows平台上的一个强大的调试器工具,由微软提供。
它主要用于用户模式和内核模式下的调试和分析应用程序和操作系统的问题。
以下是WinDbg的一些主要特点和用途:
-
用户模式和内核模式调试:WinDbg可以用于调试用户模式(例如应用程序)和内核模式(例如操作系统内核)下的程序。它提供了一系列命令和功能,允许开发人员检查和分析应用程序的行为和执行过程。
-
内存分析和调试:WinDbg可以帮助开发人员进行内存分析,识别和解决内存相关问题,如内存泄漏、无效内存访问等。它提供了强大的堆栈跟踪功能,允许分析深层次的程序执行路径。
-
调试崩溃和错误:WinDbg可以在应用程序崩溃时帮助开发人员收集信息,确定崩溃的原因并定位问题所在。通过加载崩溃时生成的转储文件(dump file),开发人员可以深入分析崩溃的堆栈和内存状态。
-
扩展性和脚本支持:WinDbg提供了扩展性和脚本支持,允许开发人员编写自定义脚本和插件来扩展其功能。这使得WinDbg可以根据具体需求进行定制化和自动化分析。
请注意,WinDbg是一个功能强大但也复杂的调试器工具,对于初学者可能需要一定的学习和熟悉过程。一般建议在进行高级调试和问题分析时使用,同时结合相关的文档和教程,以最大限度地发挥其功能和优势。
2.4.2 安装和操作步骤
以下是使用WinDbg进行调试的一般操作步骤:
-
下载和安装:从微软的官方网站(https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools)下载合适的WinDbg版本,并按照指示进行安装。
-
设置符号路径:在使用WinDbg之前,需要设置符号路径以便正确加载符号文件。在WinDbg中,使用以下命令设置符号路径:.sympath 。符号路径可以是本地文件夹或符号服务器的URL。
-
打开目标程序:在WinDbg中,选择 “File”(文件)菜单,然后选择 “Open Executable”(打开可执行文件)。选择您要调试的目标程序,并确保选择正确的机器类型(32位或64位)。
-
设置调试选项:在WinDbg中,选择 “File”(文件)菜单,然后选择 “Symbol File Path”(符号文件路径)。确认之前设置的符号路径是否正确。
-
开始调试:在WinDbg中,选择 “Debug”(调试)菜单,然后选择 “Go”(继续)或按下F5键,开始调试目标程序。程序将开始在WinDbg中运行。
-
执行断点调试:在WinDbg中,使用 bp 命令设置断点,例如:bp 来设置在函数调用时触发的断点。然后使用 g 命令继续执行程序,直到断点触发停止。
-
分析堆栈和内存状态:在程序停止时,使用 kb 命令显示调用堆栈,它会展示程序执行路径。使用其他命令如 dd、da 来检查内存中的数据和内容。
-
查看变量和表达式:使用 dv 命令查看局部变量和参数的值,使用 ? 命令来计算和查看表达式的值。
-
分析崩溃转储文件:如果您有崩溃时生成的转储文件(dump file),可以使用WinDbg打开它进行分析。在WinDbg中,选择 “File”(文件)菜单,然后选择 “Open Crash Dump”(打开崩溃转储文件)。
以上步骤提供了基本的WinDbg使用方法,适用于一般调试和分析任务。然而,WinDbg是一种功能丰富的调试工具,还有许多高级命令和功能可用于不同的调试和分析场景。请参考WinDbg的文档和教程以了解更多详细信息和命令。
2.5 Windows进程内存监控工具
-
使用任务管理器:
- 按下Ctrl + Shift + Esc键打开任务管理器(或者右键点击任务栏,选择“任务管理器”)。
- 切换到“详细信息”选项卡。
- 找到“内存”列,点击以按照内存使用量对进程进行排序。
- 查找并查看内存使用量较高的线程。
2.6 Windowx线程内存 监控工具
在Windows中,任务管理器和性能监视器只能查看进程级别的内存占用情况,而无法直接查看线程级别的内存占用情况。要查看线程级别的内存占用情况,您可能需要使用一些特定的工具和方法。
一个可能的解决方案是使用Windows性能工具集(Windows Performance Toolkit),它是一个包含多个性能分析器工具的集合。其中,可以使用“xperf”命令行工具来收集和分析线程级别的性能数据,包括内存占用。
下面是使用Windows性能工具集来查看线程级别内存占用的大致步骤:
-
下载并安装Windows Performance Toolkit。它是Windows ADK(Windows Assessment and Deployment Kit)的一部分,可以从Microsoft官方网站上下载。
-
打开命令提示符,并使用管理员权限运行。
-
使用以下命令开始性能跟踪:
xperf -on PROC_THREAD+LOADER+VIRTUAL_ALLOC -stackwalk VirtualAlloc+VirtualFree -buffersize 1024 -MaxFile 256 -FileMode Circular && timeout -1 && xperf -d merged.etl
-
在跟踪期间,进行一些操作,触发线程内存占用的情况。
-
在命令提示符处按Ctrl+C来停止跟踪。
-
使用以下命令来生成报告:
xperf -i merged.etl -o summary.txt -a dumper
-
打开生成的summary.txt文件,可以在其中找到线程级别的内存占用信息。
请注意,使用Windows Performance Toolkit需要一些熟悉和理解。建议在使用之前先了解更多有关该工具集的信息和文档。
您可以通过以下步骤在Microsoft官方网站上下载并安装Windows Performance Toolkit(一部分Windows ADK):
-
访问Microsoft官方网站的Windows ADK下载页面:https://docs.microsoft.com/en-us/windows-hardware/get-started/adk-install
-
滚动页面并找到“Windows ADK 下载链接”,然后单击它。
-
在下载页面上,选择适合您操作系统版本的最新版本的Windows ADK。
-
单击所选版本旁边的下载链接,然后开始下载Windows ADK安装程序。
请注意,Windows ADK是一个大型的下载文件,下载和安装过程可能需要一些时间。一旦下载完成,您可以按照安装向导的指导完成安装过程,其中包含了Windows Performance Toolkit等一系列性能工具。
希望这可以帮助您获取Windows Performance Toolkit!如果还有其他问题,请随时向我提问。
2.7 API函数获取线程级内存使用情况
在Windows操作系统中,任务管理器和性能监视器只能查看进程级别的内存占用情况,无法直接查看线程级别的内存占用情况。
要查看线程级别的内存占用情况,可以使用一些编程工具和API来获取线程的内存使用统计信息。其中,Windows API中的GetProcessMemoryInfo函数可以获取指定进程中所有线程的内存使用情况。
以下是一个示例代码,演示如何使用C++和Windows API获取线程级别的内存占用情况:
#include
#include
#include
int main()
{
DWORD processId = GetCurrentProcessId();
HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
if (processHandle == nullptr)
{
std::cerr “QML Profiler”。 运行应用程序,QML Profiler 将自动开始记录性能数据。
使用 QML Profiler 的各个视图来分析应用程序的性能数据。您可以查看时间线、函数调用、内存使用和动画效果的相关信息。
请注意,QML Profiler 是一个强大而丰富的工具,可以帮助您优化 QML 应用程序的性能。使用它可以发现潜在的性能问题并采取相应的优化措施。然而,在进行性能分析和优化之前,建议先了解 QML 的最佳实践,并根据具体的应用程序需求进行优化。
精华:
(1)QT内存检测工具:qml profiler 辅助性能监控
(2)Windows内存检测工具:Dr. Memory

![[QT编程系列-43]: Windows + QT软件内存泄露的检测方法](https://img-blog.csdnimg.cn/fb8869b4e71a4ccf949e09120299a7ea.png)