mtrace 使用心得: 报得很详细, 但对一些库之类的报得不一定准确. mtrace 是工作原理: 就是对malloc,free 等函数进行了hook 使用: 见实例. 简述为: 甲: 编写 1. 包含"mcheck.h" 2. 设置环境变量,MALLOC_TRACE, 指明输出的文件名. 3. 调用mtrace函数. 乙: 编译: 然后编译时加上-g debug选项, 还要加上-no-pie 去掉位置无关运行选项生成可执行代码. 丙: 执行 运行可执行文件,生成MALLOC_TRACE 指定的文件. 丁: 分析 mtrace <exe> <output> 若有debug信息,将输出泄露处源码位置信息
下面给一个实例: 如果不是qt框架, 则很简单, 只报了一条内存泄露. 如果是qt框架, 报出了400多条库内存泄露,还好自己测试的那条也报出来了, 我相信库内存泄露是误报! 拿我的一个比较复杂的工程来测试,竟然报出了21万多条的系统库及第三方库内存泄露信息,根本没法分析. 这些99.99%是误报.
考虑其malloc, free hook 的思想值得借鉴, 故我还是认真研究了一下,并附上测试代码和环境.
a. 源码
$ cat main.cpp
#include <mcheck.h>
#include <stdlib.h>
#include <stdio.h>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc,argv);
setenv("MALLOC_TRACE", "output", 1);
mtrace();
void *p = malloc(100);
return a.exec();
}
?b. 编译环境
$ cat qt.pro
######################################################################
# Automatically generated by qmake (2.01a) Tue Mar 9 10:56:06 2021
######################################################################
TEMPLATE = app
QT+=widgets
TARGET = qt
INCLUDEPATH += .
CONFIG+=debug
QMAKE_LFLAGS += -no-pie
# You can make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# Please consult the documentation of the deprecated API in order to know
# how to port your code away from it.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
# Input
SOURCES += main.cpp
结果:
$ mtrace qt output
- 0x00007fb1c4007b30 Realloc 177 was never alloc'd 0x7fb1ea0ae4d1
- 0x0000000000da6bd0 Free 1352 was never alloc'd 0x7fb1e4ef9e2d
- 000000000000000000 Free 1402 was never alloc'd 0x7fb1ea1bfde9
.... 此处忽略很多
Memory not freed:
-----------------
Address Size Caller
.... 此处忽略很多
0x0000000000e8baa0 0x150 at 0x7fb1e4f5d602
0x0000000000e8e0a0 0x150 at 0x7fb1e4f5d602
0x0000000000e8eb60 0x93 at 0x7fb1ea07bc3d
0x0000000000e94b10 0x2a at 0x7fb1e240db2f
0x0000000000e95ae0 0x64 at /home/hjj/test/test_qlabel/main.cpp:11 // 只有这一条是有用的!!!
0x0000000000e9cd80 0xe8 at 0x7fb1e240bbe0
.... 此处忽略很多
|