内存泄漏定位工具之 mtrace(二)
1 前言
mtrace(memory trace),是 GNU Glibc 自带的内存问题检测工具,它可以用来协助定位内存泄露问题。它的实现源码在glibc源码的malloc目录下,其基本设计原理为设计一个函数 void mtrace (),函数对 libc 库中的 malloc/free 等函数的调用进行追踪,由此来检测内存是否存在泄漏的情况。
上篇讲到如何使用 mtrace 检查可执行程序中的内存泄漏,可以定位到源码的行数,但是存在一个问题,它没办法直接显示动态库所在的源码行数,而 Linux 开发动态库的使用是十分常见的,那么该篇就讲讲 mtrace 如何定位动态库中的内存泄漏问题。
2 使用方式
首先我们需要在当前目录下创建两个文件(一个编译成动态库,另一个编译成可执行文件)
2.1 源码示例
inter.c 动态库源码
#include <stdlib.h>
#include <stdio.h>
void InterTest(void)
{
int *p = (int *)malloc(10 * sizeof(int));
printf("InterTest: p = %p\n", p);
}
编译动态库(-g 必须的,不然定位源码位置都是 ???)
gcc -g inter.c -fPIC -shared -o libinter.so
可执行文件 test.c(和上篇中的测试代码比较,多个动态库的接口调用和睡眠等待时间)
#include <mcheck.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
// 测试代码,没有接口头文件,所以使用 extern
extern void InterTest(void);
int main(int argc, char **argv)
{
mtrace(); // 开始跟踪
char *p = (char *)malloc(100);
free(p);
p = NULL;
InterTest();
p = (char *)malloc(100);
muntrace(); // 结束跟踪,并生成日志信息
int wait = 20;
//等待的目的是方便后面操作
while (wait--)
{
sleep(1);
printf("wait = %d\n", wait);
}
return 0;
}
编译成可执行文件
gcc -g test.c -L"/home/const/workspace/memtest" -linter -o test
2.2 运行程序
首先先设置生成跟踪的日志路径
export MALLOC_TRACE=./test.log
接着执行程序,同时 ps 查看当前可执行程序的 PID
./test & // & 的作用是后台运行,方便在等待期间进行 ps 等操作
const@server:~/workspace/memtest$ ps
PID TTY TIME CMD
1631 pts/62 00:00:00 bash
10723 pts/62 00:00:00 test
10745 pts/62 00:00:00 ps
可以看到此时的 test 执行程序的 PID 为 10745,接着输入以下指令查看加载的动态库信息(确保 test 还在执行)
const@server:~/workspace/memtest$ cat /proc/10723/maps
00400000-00401000 r-xp 00000000 08:01 144706317 /home/const/workspace/memtest/test
00600000-00601000 r--p 00000000 08:01 144706317 /home/const/workspace/memtest/test
00601000-00602000 rw-p 00001000 08:01 144706317 /home/const/workspace/memtest/test
021f8000-02219000 rw-p 00000000 00:00 0 [heap]
7f59842e3000-7f59844a3000 r-xp 00000000 08:16 4723539 /lib/x86_64-linux-gnu/libc-2.23.so
7f59844a3000-7f59846a3000 ---p 001c0000 08:16 4723539 /lib/x86_64-linux-gnu/libc-2.23.so
7f59846a3000-7f59846a7000 r--p 001c0000 08:16 4723539 /lib/x86_64-linux-gnu/libc-2.23.so
7f59846a7000-7f59846a9000 rw-p 001c4000 08:16 4723539 /lib/x86_64-linux-gnu/libc-2.23.so
7f59846a9000-7f59846ad000 rw-p 00000000 00:00 0
7f59846ad000-7f59846ae000 r-xp 00000000 08:01 144706316 /home/const/workspace/memtest/libinter.so
7f59846ae000-7f59848ad000 ---p 00001000 08:01 144706316 /home/const/workspace/memtest/libinter.so
7f59848ad000-7f59848ae000 r--p 00000000 08:01 144706316 /home/const/workspace/memtest/libinter.so
7f59848ae000-7f59848af000 rw-p 00001000 08:01 144706316 /home/const/workspace/memtest/libinter.so
7f59848af000-7f59848d5000 r-xp 00000000 08:16 4723525 /lib/x86_64-linux-gnu/ld-2.23.so
7f5984a9e000-7f5984aa1000 rw-p 00000000 00:00 0
7f5984ad3000-7f5984ad4000 rw-p 00000000 00:00 0
7f5984ad4000-7f5984ad5000 r--p 00025000 08:16 4723525 /lib/x86_64-linux-gnu/ld-2.23.so
7f5984ad5000-7f5984ad6000 rw-p 00026000 08:16 4723525 /lib/x86_64-linux-gnu/ld-2.23.so
7f5984ad6000-7f5984ad7000 rw-p 00000000 00:00 0
7fffedca8000-7fffedcca000 rw-p 00000000 00:00 0 [stack]
7fffedde7000-7fffeddea000 r--p 00000000 00:00 0 [vvar]
7fffeddea000-7fffeddec000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
2.3 分析定位
首先输入指令得到内存泄漏信息
const@server:~/workspace/memtest$ mtrace test ./test.log
Memory not freed:
-----------------
Address Size Caller
0x00000000021f8450 0x64 at /home/const/workspace/memtest/test.c:19
0x00000000021f84c0 0x28 at 0x7f59846ad702
0x00000000021f84f0 0x400 at 0x7f59843501d5
从日志文件中可以看到,可执行文件的内存泄漏直接就显示了源码的具体位置,而动态库中的泄漏没有具体显示,只是机器码的地址信息,则 libinter.so 的加载地址为 0x7f59846ad000-0x7f59848af000,其中上述符合的为 0x7f59846ad702,减去 libinter.so 的 base 地址 0x7f59846ad000得到相对偏移地址为 0x702。
通过使用 "addr2line" 命令工具,得到动态库源文件的行数,定位内存泄漏的位置。
const@server:~/workspace/memtest$ addr2line -e libinter.so 0x702
/home/const/workspace/memtest/inter.c:6
至于最后一行的 0x00000000021f84f0 0x400 at 0x7f59843501d5,通过地址比较不难看出是 /lib/x86_64-linux-gnu/libc-2.23.so 中的内存信息,通过上述相同的操作打印的内容可能是 ??,原因是没有 -g 编译后的调试信息;这个其实可以忽略,标准库中基本不会存在这种问题,这种属于可执行程序运行结束后相关资源(后期自动回收处理)还没有及时释放(可以屏蔽动态库函数的调用和睡眠函数,这个就不存在了)。
内存泄漏定位工具之 mtrace(二)的更多相关文章
- 内存泄漏定位工具之 valgrind 使用
1 前言 前面介绍了 GCC 自带的 mtrace 内存泄漏检查工具,该篇主要介绍开源的内存泄漏工具 valgrind,valgrind 是一套 Linux 下,开放源代码的动态调试工具集合,能够检测 ...
- 内存泄漏分析工具tMemMonitor (TMM)使用简介
C/C++由于灵活.高效的优点一直以来都是主流的程序设计语言之一,但是其内存的分配与释放均由程序员自己管理,当由于疏忽或错误造成程序未能释放不再使用的内存时就会造成内存泄漏.在大型.复杂的应用程序中, ...
- Cocos开发中性能优化工具介绍之Visual Studio内存泄漏检测工具——Visual Leak Detector
那么在Windows下有什么好的内存泄漏检测工具呢?微软提供Visual Studio开发工具本身没有什么太好的内存泄漏检测功能,我们可以使用第三方工具Visual Leak Detector(以下简 ...
- C++内存泄漏检测工具
C++内存泄漏检测工具 1.VC自带的CRT:_CrtCheckMemory 调试器和 CRT 调试堆函数 1.1用法: /************************************ ...
- C/C++的内存泄漏检测工具Valgrind memcheck的使用经历
Linux下的Valgrind真是利器啊(不知道Valgrind的请自觉查看参考文献(1)(2)),帮我找出了不少C++中的内存管理错误,前一阵子还在纠结为什么VS 2013下运行良好的程序到了Lin ...
- 构造函数,C++内存管理,内存泄漏定位
构造函数 1.构造顺序 虚基类构造函数,基类构造函数,类对象构造函数,自己的构造函数 2.必须使用初始化列表 (1) 引用成员,常量成员: (2) 基类没默认构造函数(自己重载覆盖了), (3)类对象 ...
- android 内存泄漏检测工具 LeakCanary 泄漏金丝雀
韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha 313134555@qq.com 内存泄漏检测工具 android 内存泄漏检测工具 ======== 内存泄漏 就是 无用的对 ...
- Cocos性能优化工具的开发介绍Visual Studio内存泄漏检测工具——Visual Leak Detector
然后,Windows下有什么好的内存泄漏检測工具呢?微软提供Visual Studio开发工具本身没有什么太好的内存泄漏检測功能.我们能够使用第三方工具Visual Leak Detector(下面简 ...
- 介绍两个非常好用的Javascript内存泄漏检测工具
内存泄漏对开发者来说一般很难检测因为它们是由一些大量代码中的意外的错误引起的,但它在系统内存不足前并不影响程序的功能.这就是为什么会有人在很长时间的测试期中收集应用程序性能指标来测试性能. 最简单的检 ...
- 内存泄漏检测工具VLD在VS2010中的使用举例
Visual LeakDetector(VLD)是一款用于Visual C++的免费的内存泄露检测工具.它的特点有:(1).它是免费开源的,采用LGPL协议:(2).它可以得到内存泄露点的调用堆栈,可 ...
随机推荐
- vue-draggable 学习和使用
vue-draggable 学习和使用 https://www.jianshu.com/p/e8ff1e1cafb1
- [转帖]PostgreSQL 统计所有数据表各自的总行数
一般来说,可以使用 count(*) 来获取具体某张表的总行数: SELECT count(0) FROM t_user; 如果想获得所有表的行数信息,可以使用以下 SQL 语句: SELECT re ...
- [转帖]《Linux性能优化实战》笔记(21)—— 网络性能优化思路
一. 确定优化目标 优化前,我会先问问自己,网络性能优化的目标是什么?实际上,虽然网络性能优化的整体目标,是降低网络延迟(如 RTT)和提高吞吐量(如BPS 和 PPS),但具体到不同应用中,每个指标 ...
- [转帖]SQL Server数据库存储总结
SQL Server数据库存储文件类型:数据文件和日志文件.数据文件以页面作为存储单元存储数据. 页面:即数据页面,数据页(Page).是系统在磁盘间中分配的一段大小为8k的连续空间. 文件头(Fil ...
- Oracle使用临时表与直接关联的性能比较
Oracle使用临时表与直接关联的性能比较 摘要 自己的数据库水平还是太low了. 之前有很多店理解过. 但是一直理解的不深入. 比如我们这边有很多使用临时表存储中间结果数据 然后对结果数据进行关联查 ...
- [转帖]Unixbench服务器综合性能测试方法及工具下载
UnixBench是一款开源的测试 unix 系统基本性能的工具,是比较通用的测试VPS性能的工具. UnixBench会执行一系列的测试,包括2D和3D图形系统的性能衡量,测试的结果不仅仅只是CPU ...
- [转帖]Springboot容器化镜像设置堆内存大小
参考资料:Best Practices: Java Memory Arguments for Containers - DZone Java 有三种方式设置最大堆内存大小: 1. -Xmx 2. -X ...
- [转帖]013 Linux 搞懂「文件所属者更改及权限的赋予」从未如此简单 (chmod、chgrp、chown)
https://my.oschina.net/u/3113381/blog/5435014 01 一图详解「ls -l」 02 两种符号区分表示文件和目录 -(横线) # 表示非目录文件 d # ...
- OpenEuler2203使用rpm方式安装Oracle19c的过程
OpenEuler2203使用rpm方式安装Oracle19c的过程 安装介质 oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpm oracle-d ...
- CentOS7最小安装注意事项
CentOS7最小安装注意事项 背景与说明 公司很多项目现在都是最小化安装的了. 自己之前为了方便都是使用GUI安装,很多地方可能都有遗漏 这里进行一下简单的安装总结, 避免以后新安装有缺失的项目 安 ...