TDengine研发分享 Windbg解决内存泄漏问题的实践和经验

小夏 科技 更新 2024-02-28

内存泄漏是一个常见的问题,它会导致程序的内存占用逐渐增加,最终导致系统资源耗尽或程序崩溃。 AddressSanitizer (ASAN) 和 Valgrind 是很好的内存检测工具,TDengine 的 CI 进程使用 ASAN。 不过,这次内存泄漏问题发生在Windows下,我们的CI还没有覆盖,所以TDENGINE研发选择使用WindBG来解决这个问题。 事实证明,在Windows下,使用WindBG也是一个不错的选择。

内存泄漏通常发生在以下情况下:

程序未正确释放分配的内存。

程序中存在循环引用,这些循环引用会导致垃圾回收器内存失败。

程序中存在内存泄漏的第三方库或组件。

内存泄漏的主要检测方法如下:

静态分析工具:程序运行时未检测到内存动态分配的指针或内存分配错误等问题。

动态分析工具:您可以使用内存分配和释放***来跟踪程序中的内存分配和释放操作,并检测是否存在内存泄漏。 但是,使用某些工具(例如 Valgrind)可能会对程序的性能产生一些影响。

调试器:windbg 和 gdb。

优点和缺点:

静态分析工具可以及早发现问题,但它们无法检测程序运行时内存的动态分配方式。

动态分析工具可以在程序运行时检测问题,但它们会影响程序性能,并且在检测大型应用程序时可能需要大量时间和资源。 但是,在资源充足的测试环境中运行不是问题,例如,ASAN 帮助我们发现了很多问题。

调试器可以在程序运行时检测问题,并提供强大的分析工具。

使用 windbg 定位内存泄漏,依靠 GLAGS 组件来记录程序在运行时请求和释放的所有内存,以及请求内存时的调用堆栈信息。 这样,在程序运行过程中,umdh组件用于记录两个快照,通过比较两个快照之间的差异,可以找出在两个快照之间的时间间隔内应用但未释放的内存应用信息。 如果存在内存泄漏,则差异结果的第一条边通常是泄漏点处的调用堆栈信息。 当然,在两次快照期间,应该尽可能地触发内存泄漏,以便更准确地定位它。 diff 结果中也会有少量的调用消息,正常应用还没来得及发布,但是在 diff 结果中可以看到调用的数量,更容易识别。

在 Windows 中导入数据时出现 taosdump 错误:

build and install latest tdengine 3.0 branch on windowsuse "taosbenchmark -i stmt -y" to create a lot of tables and data (10000 * 10000).use "taosdump -d test -o outputfile" to dump outuse "taos -s 'drop database test'" to drop databaseuse "taosdump -i inputfile" to dump in.
错误日志:taosd “tsem init failed, errno: 28”。

taosdump: dumpin**rodataimpl() ln7039 taos_stmt_execute() failed! reason: out of memory, timestamp: 1500000009256

Gflags 工具应位于以下路径: C:程序文件 (x86) Windows Kits 10 调试器 x64 Gflags,如果没有,可以直接进入 Microsoft 的官方 *** 安装:

安装完成后,运行 gflags。 命令行exe /i your_application.exe 可以设置跟踪目标并设置相关参数。 也可以双击运行,图像文件对应 i 参数,然后选择您的应用程序启动器exe,然后选择其他配置。

1.启动应用程序exe (我正在调试 taosdumpexe,所以底部是 taosdumpexe)

c:\program files (x86)\windows kits\10\debuggers\x64\gflags” -i taosdump.exe +ust

2.将 pdb 文件复制到 mysymbols 目录下,pdb 文件存储了编译程序的调试信息,这些信息是用可执行程序生成的,可以在应用生成目录中找到。

3.设置 pdb 目录。

set _nt_symbol_path=c:\mysymbols;srv*c:\mycache*
4.拍摄第一个内存快照。

"c:\program files (x86)\windows kits\10\debuggers\x64\umdh" -pn:taosdump.exe -f:c:\xstest\umdhlog\taosdump11.log
5.拍摄第二个内存快照。

"c:\program files (x86)\windows kits\10\debuggers\x64\umdh" -pn:taosdump.exe -f:c:\xstest\umdhlog\taosdump12.log
6.生成快照比较结果 (UMDH)。

"c:\program files (x86)\windows kits\10\debuggers\x64\umdh" c:\xstest\umdhlog\taosdump11.log c:\xstest\umdhlog\taosdump12.log -f:c:\xstest\umdhlog\taosdumpdiff11_12.log
由于 taosdump 程序从开始到退出都在执行大量业务工作,因此快照之间很容易发生内存泄漏。 988040 6ecf0 表示“应用程序数量发布数量”,很明显发生了内存泄漏,泄漏点在 buildrequest 函数的 SEM init 中。

+ 919350 ( 988040 - 6ecf0) 201b0 allocs backtrace9cb6973f+ 1ea5c ( 201b0 - 1754) backtrace9cb6973f allocations ntdll!rtlpallocateheapinternal+948d5 taos!heap_alloc_dbg_internal+1f6 (minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp, 359) taos!heap_alloc_dbg+4d (minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp, 450) taos!_calloc_dbg+6c (minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp, 518) taos!calloc+2e (minkernel\crts\ucrt\src\appcrt\heap\calloc.cpp, 30) taos!sem_init+5d (c:\workroom\tdengine\contrib\pthread\sem_init.c, 109) taos!buildrequest+209 (c:\workroom\tdengine\source\client\src\clientimpl.c, 192) taos!stmtcreaterequest+73 (c:\workroom\tdengine\source\client\src\clientstmt.c, 15) taos!stmtsettbname+115 (c:\workroom\tdengine\source\client\src\clientstmt.c, 588) taos!taos_stmt_set_tbname+7f (c:\workroom\tdengine\source\client\src\clientmain.c, 1350) taosdump!dumpin**rodataimpl+e25 (c:\workroom\tdengine\tools\taos-tools\src\taosdump.c, 6260) taosdump!dumpinone**rofile+3d2 (c:\workroom\tdengine\tools\taos-tools\src\taosdump.c, 7229) taosdump!dumpin**roworkthreadfp+20b (c:\workroom\tdengine\tools\taos-tools\src\taosdump.c, 7306) taosdump!ptw32_threadstart+cd (c:\workroom\tdengine\contrib\pthread\ptw32_threadstart.c, 233) taosdump!thread_start+9c (minkernel\crts\ucrt\src\appcrt\startup\thread.cpp, 97) kernel32!basethreadinitthunk+10 ntdll!rtluserthreadstart+2b
接下来勾选**并修改,C语言使用内存的自由度很高,所以也比较麻烦。 您可以看到某些路径错过了对 tsem destory 的调用。

欲了解更多详情,请看这里

要想做好,首先要磨砺你的工具,掌握更多的工具和手段,更冷静地解决问题,windbg定位内存泄漏的方法很简单,但非常有效。 但是,请务必注意,它依赖于 pdb 文件,因此请记住在发布应用程序时保留 pdb 文件。 pdb 文件包含有关程序的符号信息,这有助于我们在调试过程中查明问题。

另外,从**问题可以看出,这个内存的管理还是比较容易出错的,RAII机制可以更好的避免资源泄漏,C语言也可以通过模拟RAII达到类似的效果,虽然不如C++流畅,但也许以后可以考虑优化一下。

RAII(Resource Acquisition is Initialization)机制是一种重要的资源管理方法,它将资源的获取与对象的生命周期相关联。 通过在对象的构造函数中获取资源并在析构函数中释放资源,我们可以确保资源的正确管理,并防止资源泄漏和内存泄漏等问题。 RAII机制广泛应用于C++等编程语言中,是管理资源的有效方式。

相似文章

    展位火爆!TDengine受邀参加EDT2023中国能源和化工行业数字技术峰会

    随着大数据 物联网 人工智能 G等数字技术的蓬勃发展,能源化工与新兴技术的融合也在加速推进,推动智能化 网格化 信息化加速演进。在不稳定的外部环境下,数字化转型成为能源化工企业可持续发展的关键。月日,由辰哲文化主办的 EDT中国能源化工数字化技术峰会 在北京举行,峰会邀请了来自能源化工行业信息技术 ...

    TDengine与西电电力签约

    近年来,随着云计算和物联网技术的快速发展,传统电力行业正朝着数字化 信息化 智能化的大趋势迈进。电力行业在传统业务基础上,构建了信息网络 通信网络和能源网络,致力于实现发电 输电 变电 配电 用电的实时智能联动。在此过程中,电力物联网领域产生的数据采集量呈现出一流的增长态势,应对海量数据处理需求成为...

    TDengine与吉诚电子签约

    随着电力系统的复杂度和数据量的增加,电力负载 电压 频率等海量时序数据需要更高效的存储和处理能力,以保证数据的可靠性和实时性。此外,电力系统还需要对实时数据进行快速分析和决策,以确保电网的稳定运行。然而,传统的数据处理解决方案往往难以满足这些数据处理需求。为了应对这些挑战,越来越多的公用事业公司正在...

    百色茶馆互联网研发团队分享传统企业数字化升级

    年是 web 年。今年是数字化升级 智能化传统企业的关键一年,也是传统企业同行业竞争 元宇宙时代重新崛起的划时代之年 数字化 业务数据化 首先允许通过数据记录业务流程。数字化 业务数字化 即让企业在生产 采购 销售过程 客户服务 现金流等过程中产生的数据,用数据记录在业务系统上。首先,信息化 数字化...

    TDengine与中船集团9号签约,助力航运业智能化转型升级

    在大数据时代,船舶智能化已成为造船和航运发展的必然趋势。作为 中国制造 中明确的重点发展领域,智能船舶代表着船舶的未来发展方向,对航运业转型升级至关重要。其中,大数据的处理和应用成为船舶智能化改造成功的关键因素之一。近日,TDEngine 与中国船舶第九研究院第九设计研究院,以下简称中国船舶第九研究...