Linux与Windows平台内存泄漏定位方法,对象计数法你知道吗?

检测维修 0 186

一、前言

Linux系统配备valgrind工具,能很高效协助发现内存泄漏问题,由于Linux在开发环境中多用于部署服务器,并且具备开源特性,因此解决故障时往往能遵循较为一致的操作规范。相比之下,Windows系统下服务器和客户端开发人员所采用的调试手段存在显著差异。下面结合我的实际经验,整理下常见定位内存泄漏的方法。

我们的分析基于正式发布版本,因为在测试调试模式下,借助VLD这个库或者CRT库自带的内存检测功能,可以识别出内存泄漏,这个过程比较容易。而服务器运行时会出现很多问题,这些故障往往需要在线上高并发状态下才能暴露出来,所以探讨测试版的调试技巧作用不大。

二、对象计数

创建对象时数量增加,销毁对象时数量减少,定期输出当前对象的总数

优点:没有性能开销,几乎不占用额外内存。定位结果精确。

这种做法存在弊端,它要求改动已有程序代码,然而对于无法更改的部分,比如外部库、标准容器以及脚本错误,就难以追踪问题。

三、重载new和delete

技术:替换掉标准的内存管理函数,追踪内存申请和释放的位置,并记录下调用过程,随后周期性地输出相关信息。

优点:没有看出

这种做法存在不足之处,因为它是一种强制性的技术,要求把相关声明置于众多代码片段的开头部分,目的是让特定指令能够全局生效,覆盖掉所有的内存管理操作。在多任务环境下,追踪资源使用情况必须借助同步机制,这会带来性能损耗。同时,维持记录信息需要消耗可观的数据存储空间,直接挤占了程序运行时所占用的内存资源。

四、Hook Windows系统API

采用微软的detours工具,拦截内存分配的函数:HeapAlloc/HeapRealloc/HeapFree,这些函数是new/malloc的内部实现,追踪内存分配的各个节点,定时输出相关信息。

长处在于采取无入侵手段,无需改动原有文档,在挂钩接口后,将资源的分配与释放操作迁移至专属处理函数,检测覆盖广泛,不论是对外部程序、脚本工具或其他支持库,均可进行数据统计。

缺点:记录内存需要占用大量内存,而且多线程环境需要加锁。

五、使用DiagLeak检测

微软研发的内存溢出检测软件,运作机制与拦截函数指针类似。借助LDGraph呈现内存分配状况,有助于定位问题。

c#内存泄漏检测工具_Hook Windows系统API检测内存泄漏_定位Linux内存泄漏

在开发环境的构建设置中设定正式构建同样附带追踪信息,部署时,将符号文件与可执行程序一同分发。

程序执行之后,启动LeakDiag,设定符号路径

周期性地记录目标程序的内存使用状况,借助LDGraph来展示内存分配的增长趋势,以便识别内存是否存在泄漏现象。

优势:与hookapi方式类似,能够实现无入侵式调整,无需进行任何代码层面的变更。监控覆盖广泛。通过可视化手段,可以清晰地了解调用栈的完整情况。

性能方面存在不足,挂钩分配时需要加锁,并且要遍历堆栈,不过不会占用目标程序的固有内存空间。

六、总结

线上运行环境里,针对体积大的数据项,应当通过数量统计来识别,这样查找起来既迅速又精确,并且几乎不造成任何效率损失。而在面向公众的测试期间,可以借助LeakDiag工具来协助诊断,原因是那个阶段同时运行的任务数量还不算多,因此效率损耗尚在可接受范围内。网络普及推广期间,借助钩子接口技术,配合管理命令调节特定时段的监控,能够最大程度减轻用户感受(服务器效能降低引发响应迟缓)。

相关推荐: