一、如何检测用户空间内存泄漏?
在【Linux内存泄漏专题】如何分析Linux内存泄漏问题?-CSDN博客中我们提到了排查 Linux 内存泄漏的一般步骤,如何确定是用户空间存在内存泄漏呢?基本排查步骤如下:
1.1、查看 /proc/meminfo 中的 Anon/File 参数
若发现 /proc/meminfo 中的 anon、file 或 Shmem 数值有比较明显的增加,则怀疑进程内存泄漏。
1.2、ps -l 命令精确定位
使用 ps -l 命令进一步排查内存泄漏在哪个进程,这里主要关注 RSS 数值。
1.3、df -Th、du 命令查看 /tmp 目录
对于 Shmem 数值增加命令,可以使用 df -Th 和 du 命令查看 /tmp 目录,来定位共享内存的位置。
二、应用进程内存泄漏检测工具 - Valgrind
2.1、Valgrind 工具集简介
Valgrind一套工具集,通常用来分析程序性能以及程序中存在的内存问题,Valgrind工具集的官网:Valgrind Home,Valgrind工具集包含以下工具:
1)Memcheck
它是一个内存错误检测器,有了它的帮助可以让C和C++程序更加正确。
2)Cachegrind
它是一个缓存和分支预测分析器,它可以帮助你让你的程序运行得更快。
3)Callgrind
它是一个调用图生成缓存分析器,它与Cachegrind有一些重叠,但也收集了Cachegrind没有的一些信息。
4)Helgrind
它是一个线程错误检测器,它可以帮助你使你的多线程程序更加正确。
5)DRD
它也是一个线程错误检测器,它与Helgrind类似,但使用不同的分析技术,因此可能会发现不同的问题。
6)Massif
它是一个堆分析器,它可以帮助你减少程序使用的内存。
7)DHAT
它是一种不同类型的堆分析器,它可以帮助你了解块寿命、块利用率和布局效率低下的问题。
2.2、Memcheck 工具
这里我们重点介绍下内存检测工具 - memcheck,这是我们检测用户空间进程内存泄漏的核心工具。
2.2.1、功能介绍
memcheck可以检测以下类型的内存错误:
1)访问非法地址
2)使用未定义/未初始化的值
3)不正确的释放堆内存,例如:double-free
4) memcpy及相关函数中src和dst重叠
5)将可疑值(可能是负值)传递给内存分配函数的size参数
6)realloc中使用长度为0
7)使用不是2的幂的对齐值
8)内存泄漏
2.2.2、命令用法
Valgrind工具集中最常用的工具就是 memcheck,它通过 --tool 选项来指定,若不指定默认就是memcheck,下面是Valgrind使用memcheck扫描程序的命令:
$ valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all --track-origins=yes ./data/mipc_submonitor
下图是该工具返回的相关结果信息,我们来一一介绍下这里面需要关注的信息。
2.2.3、内存泄漏类型
从上图中LEAK SUMMARY我们可以看到memcheck工具上报的泄漏类型有五种,这里还显示了字节数以及它们所在的块数。
1)definitely lost
确定地内存泄漏是最严重的内存泄漏类型,因为这些内存没法被使用或者恢复,最常见的场景是在一个函数内存使用malloc申请内存后没有free,当程序退出后之前申请的这部分内存就没办法被跟踪使用。
2)indirectly lost
这种情况下的内存泄漏不是因为没有指向它的指针,而是因为指向它的所有块本身都丢失了。
3)possibly lost
这意味着一个或多个指针的链已找到块,但至少有一个指针是内部指针。
4)still reachable
这种类型表示当前系统中存在没有被释放的内存,但是,程序可以跟踪到它,所以,memcheck工具会认为它不是一个严重问题,为了进一步确认这些未释放的内存是进程正常使用的,还是可能是内存泄漏点,这个还是需要打开calltrace来进一步分析。