内存泄漏定位工具之 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).它可以得到内存泄露点的调用堆栈,可 ...
随机推荐
- prefer-rest-params
使用剩余参数代替 arguments (prefer-rest-params) 剩余参数来自于ES2016.可以在可变函数中使用这个特性来替代arguments变量.arguments没有Array. ...
- location对象的方法
location.assign() 跟href一样,可以跳转页面(也称为重定向页面). location.replace() 替换当前页面,因为不记录历史,所以不能后退页面. location.rel ...
- SpringBoot 动态数据源
SpringBoot 实现动态数据源切换 Spring Boot + Mybatis Plus + Druid + MySQL 实现动态数据源切换及动态 SQL 语句执行. 项目默认加载 applic ...
- Kafka 社区KIP-405中文译文(分层存储)
原文链接:https://cwiki.apache.org/confluence/display/KAFKA/KIP-405%3A+Kafka+Tiered+Storage 译者:Kafka KIP- ...
- 大数相加 a+b
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<ctype.h> #i ...
- Linux: CPU C-states
0. Overview There are various power modes of the CPU which are determined based on their current usa ...
- Windows 下 Outlook 点击关闭最小化和开机自动运行
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- 基于AHB_BUS Clac slave详解
基于AHB-APB BUS slave详解 1.目录 高内聚:让模块的功能更集中,更单一. AMBA总线例子,需要有一个模块和AMBA进行交互,就可以单独将与AHB总线进行交互的部分作为一个模块.经常 ...
- css - 伪元素清除浮动
.clearfix:after{ content:""; /*设置内容为空*/ height:0; /*高度为0*/ line-height:0; /*行高为0*/ display ...
- Raid卡型号的简单辨认与问题发现过程
Raid卡型号的简单辨认与问题发现过程 背景 同事给了一个awr报告. !-_-! 其实我看不懂. 但是他告诉我 有大量的log file sync 的等待事件. 然后又给了一套其他的文件, 发现lo ...