内存泄漏定位工具之 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).它可以得到内存泄露点的调用堆栈,可 ...
随机推荐
- kafka如何保证数据的消息不丢失(最简洁)
一.kafka 本身配置层面1.1.replication.factor 默认值1创建kafka的topic时候,每个分区设置的副本数, 根据broker数量酌情设置, 建议业界通常做法设置为3 1. ...
- S3C2440移植uboot之新建单板_时钟_SDRAM_串口
上一节S3C2440移植uboot之启动过程概述我们我们分析了uboot启动流程,这节将开始新建一块单板支持S3C2440. 目录 1.新建单板 1.1 将2410的单板文件夹拷贝成2440: 1.2 ...
- uni-app实现登录功能
https://www.bilibili.com/video/BV1jy4y1B7pw?p=140&spm_id_from=pageDriver uniapp封装request,设置请求头与t ...
- 2023全国大学生电子设计竞赛H题全解 [原创www.cnblogs.com/helesheng]
2023年又是全国大学生电子设计竞赛年,一如既往的指导学生死磕H题.8月2日看到公布的赛题,我自己还沾沾自喜,觉得今年学生用嵌入式系统和数字信号处理知识就可以完成这题,赛前都辅导过,应该成绩不差.哪想 ...
- KSP(坎巴拉)萌新感悟
1.为什么降落月球等无大气星球时减速为亚轨道之后便不再减速,等到快坠落的时候在满节流阀极限减速最省燃料? 因为我们的dv是确定的,燃料能给我们带来一定量的冲量,却因此可以带来不一定量的动量,显然速度越 ...
- 使用 Docker 安装 MongoDB 数据库
by emanjusaka from https://www.emanjusaka.top/2024/01/docker-create-mongo-db 彼岸花开可奈何 本文欢迎分享与聚合,全文转载请 ...
- 15-TTL与非门
TTL与非门 集成电路有两大类COMOS和TTL(三极管) 电路结构 工作原理 多发射结的三极管,两个输入之间是与的关系 输入低电平 输入高电平 A.B都是高电平 倒置放大 压差大的先导通 T3,T4 ...
- 【TouchGFX】visua studio 自定义路径宏
很好奇 touchgfx 的 visual studio 工程文件中路径符号 $(TouchGFXReleasePath)是哪里定义的,经查这就是一个宏替换 自定义宏方式
- 揭秘 Docker 网络:手动实现 Docker 桥接网络
本文将带领读者探索 Docker 桥接网络模型的内部机制,通过手动实现 veth pair.bridge.iptables 等关键技术,揭示网络背后的运作原理. 如果你对云原生技术充满好奇,想要深入了 ...
- java - 字符串转数字
Integer.valueOf("str").intValue(): Integer.valueOf("123").intValue():