给你一款产品如何检测内存泄漏

版权声明: https://blog.csdn.net/qq_41880190/article/details/89404840

Windows 下内存泄漏检测工具 VLD

VLD 的使用

通常在 main 函数所在的 cpp 文件中 include <vld.h> 即可,运行程序,退出后产生检测报告

注意事项

  • 如果有 include "stdafx.h",则 include <vld.h> 放在其后,否则放在最前面

  • VLD 仅在 debug 版本有效

  • 如果想将产生的日志文件保存在文件中,需要将 vld.ini(VLD 安装目录下)复制到可执行文件目录下,然后做如下修改

  • ReportFile =.\memory_leak_report.txt 
    ReportTo = both 
    

例子

#include <vld.h>
int main()
{
    auto* p1 = new int;
    auto* p2 = new int;
    return 0;
}

检测报告

img

报告中显示了有两处内存泄漏,这是在 VS 中的输出窗口(CTRL + ALT + O)中,双击对应行即可定位到内存泄漏处

Linux 下检测内存泄漏的工具

mtrace检测内存泄露

mtrace其实是GNU扩展函数,用来跟踪malloc。

mtrace为内存分配函数(malloc, realloc, memalign, free)安装hook函数。这些hook函数记录内存的申请和释放的trace信息。
在程序中,这些trace信息可以被用来发现内存泄漏和释放不是申请的内存。
当调用mtrace,mtrace会检查环境变量MALLOC_TRACE。该环境变量应该包含记录trace信息的文件路径。如果文件可以被成功打开,它的大小被截断为0。
如果MALLOC_TRACE没有设置,或者设置的文件不可用或者不可写,那么将不会安装hook函数,mtrace不生效。

扫描二维码关注公众号,回复: 6151153 查看本文章

更对详细信息:man 3 mtrace

mtrace使用

mtrace 能监测程序是否内存泄露

  • 在程序起始处包含 #include <mtrace.h>

  • 更改环境变量:export MALLOC_TRACE=”mtrace.out”可以加入如下代码

  • setenv("MALLOC_TRACE", "mtrace.out", 1);
    
  • 调用函数 mtrace()

  • 编译程序时带上 -g 选项

  • 运行程序一次,尽量调用所有程序内的函数。这时调试信息就已经被写入我们指定的 mtrace.out 文件中

  • mtrace a.out mtrace.out 查看内存监测情况

检测报告

img

Kmemleak 检测工具介绍

Kmemleak工作于内核态是内核自带的内核泄露检测工具, 其源代码位于mm/kmemleak.c

Kmemleak工作于内核态,Kmemleak 提供了一种可选的内核泄漏检测,其方法类似于跟踪内存收集器。当独立的对象没有被释放时,其报告记录在 /sys/kernel/debug/kmemleak中,Kmemcheck能够帮助定位大多数内存错误的上下文。

Kmemleak使用

  • 首先CONFIG_DEBUG_KMEMLEAKKernel hacking中被使能.

  • 查看内核打印信息详细过程如下:

    • 挂载debugfs文件系统

      mount -t debugfs nodev /sys/kernel/debug/
      
    • 开启内核自动检测线程

      echo scan > /sys/kernel/debug/kmemleak
      
    • 查看打印信息

      cat /sys/kernel/debug/kmemleak
      
    • 清除内核检测报告,新的内存泄露报告将重新写入/sys/kernel/debug/kmemleak

      echo clear > /sys/kernel/debug/kmemleak
      

内存扫描参数可以进行修改通过向/sys/kernel/debug/kmemleak 文件写入。 参数使用如下

off 禁用kmemleak(不可逆)
stack=on 启用任务堆栈扫描(default)
stack=off 禁用任务堆栈扫描
scan=on 启动自动记忆扫描线程(default)
scan=off 停止自动记忆扫描线程
scan=<secs> 设置n秒内自动记忆扫描
scan 开启内核扫描
clear 清除内存泄露报告
dump=<addr> 转存信息对象在<addr>

通过“kmemleak = OFF”,也可以在启动时禁用 Kmemleak 在内核命令行。在初始化 kmemleak 之前,内存的分配或释放这些动作被存储在一个前期日志缓冲区。这个缓冲区的大小通过配CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE设置。

Kmemleak动态检测原理

通过的 kmalloc、vmalloc、kmem_cache_alloc 等内存分配会跟踪其指针,连同其他的分配大小和堆栈跟踪信息,存储在 PRIO 搜索树。相应的释放函数调用跟踪和指针就会从 kmemleak 数据结构中移除。
分配的内存块,被认为是独立的,如果没有指针指向它起始地址或块的内部的任何位置,可以发现扫描内存(包括已保存的寄存器)。这意味着,有可能没有办法为内核通过所分配的地址传递块到一个释放函数,因此,该块被认为是一个内存泄漏。

扫描算法步骤:

  • 标记的所有分配对象为白色(稍后将剩余的白色物体考虑独立的)

  • 扫描存储器与所述数据片段和栈开始,检查对地址的值存储在PRIO搜索树。如果一个白色的对象的指针被发现,该对象将被添加到灰名单

  • 扫描的灰色对象匹配的地址(一些白色物体可以变成灰色,并添加结束时的灰名单),直到黑色集结束

  • 剩下的白色物体被认为是独立儿,并报告写入/sys/kernel/debug/kmemleak。
    一些分配的内存块的指针在内核的内部数据结构和它们不能被检测为孤儿。对避免这种情况,kmemleak也可以存储的数量的值,指向一个内的块的地址范围内的地址,需要找到使块不被认为是泄漏.

kmem相关函数

函数 功能
kmemleak_init 初始化kmemleak
kmemleak_alloc 一个内存块分配的通知
kmemleak_alloc_percpu 通知的一个percpu的内存块分配
kmemleak_free 通知的内存块释放
kmemleak_free_part 通知释放部分内存块
kmemleak_free_percpu 一个percpu内存块释放的通知
kmemleak_not_leak 当不是泄露时,标记对象
kmemleak_ignore 当泄漏时不扫描或报告对象
kmemleak_scan_area 添加扫描区域内的内存块
kmemleak_no_scan 不扫描的内存块
kmemleak_erase 删除一个指针变量的旧值
kmemleak_alloc_recursive 为kmemleak_alloc,只检查递归
kmemleak_free_recursive 为kmemleak_free,只检查递归

猜你喜欢

转载自blog.csdn.net/qq_41880190/article/details/89404840