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

内存泄漏是一种常见的问题,它会导致程序的内存占用逐渐增加,最终导致系统资源耗尽或程序崩溃。AddressSanitizer (ASan) 和 Valgrind 是很好的内存检测工具,TDengine 的 CI 过程就使用了 ASan 。不过这次内存泄漏问题发生在 Windows 下,我们 CI 暂时还没有覆盖到,因此 TDengine 研发选择使用 Windbg 来解决问题。结果证明,在 Windows 下,使用 Windbg 也是一个不错的选择。

内存泄漏的常用检测方法

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

  • 程序未正确释放已分配的内存
  • 程序中存在循环引用,导致垃圾收集器无法回收内存
  • 程序中存在内存泄漏的第三方库或组件

内存泄漏的检测方法主要包括以下几种:

  1. 静态代码分析工具:未释放的指针或内存分配错误等问题,不能检测在程序运行时动态分配内存的情况。
  2. 动态分析工具:可以使用内存分配和释放跟踪器来跟踪程序中的内存分配和释放操作,并检测是否存在内存泄漏的情况。然而,使用某些工具(如Valgrind)可能会对程序的性能产生一定的影响。
  3. 调试器:WinDbg 和 GDB。

优缺点:

  • 静态代码分析工具可以在早期发现问题,但是它们不能检测程序运行时动态分配内存的情况。
  • 动态分析工具可以在程序运行时检测问题,但是它们可能会影响程序性能,并且在检测大型应用程序时可能需要大量的时间和资源。不过在资源充足的测试环境中跑的话,就都不是问题了,比如 ASan 就帮我们发现过不少问题。
  • 调试器可以在程序运行时检测问题,并提供强大的分析工具。

实践分析

基本原理

使用 Windbg 定位内存泄露,依赖 glags 组件记录程序在运行期间所有申请和释放的内存,同时记录的还有申请内存时的调用栈信息。这样在程序运行期间,使用 umdh 组件进行两次快照记录,通过比较两次快照信息的差异,就可以发现两次快照间隔时间段中申请却并未释放的内存申请信息。如果有内存泄露,diff 结果最前边一般就是泄漏点的调用栈信息。当然,两次快照期间,要尽量触发内存泄露,才能更准确的定位。diff 结果中还会有少量正常的申请没来得及释放的调用信息,不过 diff 结果中能看到调用次数,比较容易甄别。

问题介绍

taosdump 在 windows 导入数据出错:

build and install latest TDengine 3.0 branch on Windows
use "taosBenchmark -I stmt -y" to create a lot of tables and data (10000 * 10000).
use "taosdump -D test -o outputFile" to dump out
use "taos -s 'drop database test'" to drop database
use "taosdump -i inputFile" to dump in.

错误日志:taosd “tsem_init failed, errno: 28”

Taosdump: dumpInAvroDataImpl() LN7039 taos_stmt_execute() failed! reason: Out of Memory, timestamp: 1500000009256

定位过程

配置 gflags

gflags 工具应该位于路径:C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags,如果没有的话,可以直接前往 Microsoft 的官方网站下载安装:Windows 调试工具 - Windows drivers | Microsoft Learn

安装完成后,在命令行执行 gflags.exe /i your_application.exe 可设置跟踪目标,同时可以设置相关参数。双击运行也是可以的,Image File 对应 /i 参数,选择启动程序 your_application.exe 后先按 tab 键,然后选择其他配置。

内存泄漏治理实战:TDengine 研发团队使用 Windbg 的经验分享 - TDengine Database 时序数据库

定位步骤

1. 启动 your_application.exe(我要调试的是 taosdump.exe,所以下边是 taosdump.exe)

“C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags” -i taosdump.exe +ust

2. 拷贝 pdb 文件到 mysymbols 目录,pdb 文件存储了编译后的程序的调试信息,和可执行程序一起生成,可以在应用程序生成目录中找到。

3. Set pdb 目录

set _NT_SYMBOL_PATH=c:\mysymbols;srv*c:\mycache*https://msdl.microsoft.com/download/symbols

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        allocationsntdll!RtlpAllocateHeapInternal+948D5taos!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!dumpInAvroDataImpl+E25 (C:\workroom\TDengine\tools\taos-tools\src\taosdump.c, 6260)taosdump!dumpInOneAvroFile+3D2 (C:\workroom\TDengine\tools\taos-tools\src\taosdump.c, 7229)taosdump!dumpInAvroWorkThreadFp+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<unsigned int (__cdecl*)(void *),1>+9C (minkernel\crts\ucrt\src\appcrt\startup\thread.cpp, 97)KERNEL32!BaseThreadInitThunk+10ntdll!RtlUserThreadStart+2B
泄漏点修改

接下来查看代码并修改,C 语言对内存的使用自由度很高,因此也比较麻烦。可以看到有些路径遗漏了 tsem_destory 的调用。

内存泄漏治理实战:TDengine 研发团队使用 Windbg 的经验分享 - TDengine Database 时序数据库

更加详细的代码方案请见 Fix/xsren/td 21762/sem mem leak by facetosea · Pull Request #19580 · taosdata/TDengine · GitHub

总结

工欲善其事必先利其器,掌握更多的工具和手段,在解决问题时才能比较从容,Windbg 定位内存泄漏的方式非常简单,但是很有效。不过需要注意,它依赖 pdb 文件,因此,发布应用程序时要记得保留 pdb 文件。pdb 文件包含了程序的符号信息,能够帮助我们在调试过程中准确定位问题所在。

另外,从出问题的代码可以看出,这块内存的管理方式还是比较容易出错,RAII 机制能较好的避免资源泄露,C 语言中也可以通过模拟 RAII 来达到类似的效果,虽然没有 C++ 那么流畅,也许以后可以考虑优化一下。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/708533.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM的深入理解

1、JVM&#xff08;Java虚拟机&#xff09;&#xff1a;我们java编译时候&#xff0c;下通过把avac把.java文件转换成.class文件&#xff08;字节码文件&#xff09;&#xff0c;之后我们通过jvm把字节码文件转换成对应的cpu能识别的机器指令&#xff08;翻译官角色&#xff09…

【小沐学QT】QT学习之信号槽使用

文章目录 1、简介2、代码实现2.1 界面菜单“转到槽”方法2.2 界面信号槽编辑器方法2.3 QT4.0的绑定方法2.4 QT5.0之后的绑定方法2.5 C11的方法2.6 lamda表达式方法 结语 1、简介 在GUI编程中&#xff0c;当我们更改一个小部件时&#xff0c;我们通常希望通知另一个小程序。更普…

JavaScript的书写方式

JavaScript的书写方式 目前较为流行的是第二种和第三种&#xff0c;第一种很少见。在第二种和第三种推荐使用第三种&#xff0c;因为在日常开发/工作中&#xff0c;第三种是最为常见的 1.行内式 把JS代码嵌入到html元素内部 示例代码 运行效果 由于JS中字符串常量可以使用单引…

搜维尔科技:CATIA为建筑、基础设施和城市规划提供虚拟孪生力量

超越传统项目交付方法限制的协作 复杂建筑和基础设施项目开发的设计和工程流程需要多个利益相关者和所有项目阶段的密切合作。此外&#xff0c;日益复杂的施工项目要求所有团队都依赖 CATIA 和3D EXPERIENCE 虚拟孪生技术作为“通用语言”&#xff0c;以促进协作并减少阶段之间…

K8S(kubernetes) 部署运用方式汇总

k8s 部署运用这边汇总两类&#xff0c;第一种是命令版本。第二种是文本版本&#xff0c;通过创建yaml文件方式。 此次目标&#xff1a;通过k8s创建nginx,端口80并且可以被外网访问。 kubectl get namespaces 一、创建命名空间 首先创建一个命名空间&#xff0c;有了命名空间后…

paimon表读优化-Read-optimized Table

目录 概述实践文档测试 结束 概述 paimon 版本 : 0.7 测试目标: 类似 hudi ro 表 实践 文档 Read-optimized Table 测试 0: jdbc:hive2://10.32.36.142:10009/> select * from trace_log_refdes_hive_ro$ro limit 10;24/02/28 14:24:33 INFO ExecuteStatement: Execu…

获取tensorflow lite模型指定中间层的输出

以mobilenet v2为例子&#xff0c;我已经训练好了模型&#xff0c;有tflite格式和onnx格式两种模型的权重文件&#xff0c;我想获取tflite模型在推理阶段neck部分的输出。 查看onnx模型得到neck最后一层位置 使用netron查看onnx模型结构 从name中能知道Reshape是neck的最后一…

微信小程序固定头部-CSS实现

效果图 代码逻辑&#xff1a;设置头部的高度&#xff0c;浮动固定后&#xff0c;再加个这个高度的大小的外边距 .weui-navigation-bar {position: fixed;top: 0px;left: 0px;right: 0px;height:90px; } .weui-navigation-bar_bottom{height:90px; }

SpringCloud 基本概念

开篇 学习springcloud的前提我已经认为你已经具备&#xff1a; 微服务的基本概念具备springboot的基本用法 eurake server:注册中心,对标zookeeper eurake client:服务,对标dubbo ribbon:负载均衡,对标nginx feign:与ribbon类似,目前项目没有使用,暂时就不写 hystrix:断路…

双指令集成一体控制比例放大器

双指令独立输入比例放大器是一种能够接收两个独立指令输入来控制两个比例电磁铁的比例阀放大器。 该类放大器可以同时控制两个单电磁铁比例阀&#xff0c;每一组都可以根据不同的指令输入进行独立操作。 它通常兼容多种类型的指令输入&#xff0c;如0-10V、0-5V以及4-20mA等&…

docker版本 jenkins配置gitlab自动部署

前端项目 Build steps pwd npm config set registry https://registry.npm.taobao.org npm -v node -v #npm install npm run build:prod tar -czvf QASystem.tar.gz distpwd cd /data/zhouxy37/vue_deploy tar -zxvf QASystem.tar.gz sudo mv dist QASystem cp -r QASyste…

机器人内部传感器阅读梳理及心得-速度传感器-模拟式速度传感器

速度传感器是机器人内部传感器之一&#xff0c;是闭环控制系统中不可缺少的重要组成部分&#xff0c;它用来测量机器人关节的运动速度。可以进行速度测量的传感器很多&#xff0c;如进行位置测量的传感器大多可同时获得速度的信息。但是应用最广泛、能直接得到代表转速的电压且…

fastjson序列化MessageExt对象问题(1.2.78之前版本)

前言 无论是kafka&#xff0c;还是RocketMq&#xff0c;消费者方法参数中的MessageExt对象不能被 fastjson默认的方式序列化。 一、查看代码 Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,ConsumeConcurrentlyContext context) {t…

江科大stm32学习笔记——【4-1】OLED

一.原理 1.调试方式 串口调试&#xff1a;通过串口通信&#xff0c;将调试信息发送到电脑端&#xff0c;电脑使用串口助手显示调试信息。 显示屏调试&#xff1a;直接将显示屏连接到单片机&#xff0c;将调试信息打印在显示屏上。 Keil调试模式&#xff1a;借助Keil软件的调…

resilience4j 2.0.0版本使用要求最低JDK17(使用踩坑记录)

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容&#x1f4e2;文章总结&#x1f4e5;博主目标 &#x1f50a;博主介绍 &#x1f31f;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作…

六自由度Stewart平台的matlab模拟与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1运动学原理 4.2 Stewart平台运动学方程 5.完整工程文件 1.课题概述 六自由度Stewart平台的matlab模拟与仿真&#xff0c;模拟六自由度Stewart平台的动态变化情况以及伺服角度。 2.系统仿真结果 3.核…

v-rep--websocket接口

websocket是什么 V-REP 中的 Web Socket 是一种用于在 V-REP 和外部应用程序之间进行通信的协议和技术。Web Socket 基于 TCP 连接&#xff0c;可以提供双向、实时的数据传输&#xff0c;适用于互动性或实时交互性应用。 (比如v-rep在云服务器上运行&#xff0c;通过websocke…

【国产MCU】-CH32V307-定时器同步模式

定时器同步模式 文章目录 定时器同步模式1、定时器同步模式介绍2、驱动API介绍3、定时器同步模式实例1、定时器同步模式介绍 CH32V307的定时器能够输出时钟脉冲(TRGO),也能接收其他定时器的输入(ITRx)。不同的定时器的ITRx的来源(别的定时器的TRGO)是不一样的。 通用定…

Covalent Network的长期数据可用性 获得了众多加密 KOL的肯定及支持

随着 Web3 生态系统的动态发展&#xff0c;Covalent Network&#xff08;CQT&#xff09;的关键性正在显现&#xff0c;通过提供分布式、加密安全的数据层&#xff0c;以解决长期数据可用性的问题。Covalent Network&#xff08;CQT&#xff09;不仅仅是一个工具&#xff0c;更…

企业内部文件资料如何进行加密 ——防止泄露?

企业内部文件资料的加密是防止数据泄露的关键措施之一。 www.weaem.com 以下是一些建议&#xff0c;用于在企业内部进行文件资料的加密&#xff0c;以防止数据泄露&#xff1a; 选择适合的加密技术&#xff1a; 透明加密&#xff1a;这种加密方式允许用户在不改变原有操作习惯的…