GLIBC:调试内存泄漏:如何解释mtrace()的输出
我正在调试内存泄漏问题。我正在使用获取malloc/free/realloc跟踪。我已经运行了我的程序,现在有一个巨大的日志文件。到现在为止,一直都还不错。但是我在解释文件时遇到了问题。请看以下几行:GLIBC:调试内存泄漏:如何解释mtrace()的输出,c,memory-leaks,glibc,mtrace,C,Memory Leaks,Glibc,Mtrace,我正在调试内存泄漏问题。我正在使用获取malloc/free/realloc跟踪。我已经运行了我的程序,现在有一个巨大的日志文件。到现在为止,一直都还不错。但是我在解释文件时遇到了问题。请看以下几行: @ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502570 0x68 @ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b27
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502570 0x68
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1502620 0x30
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x1501460 0xa64
奇怪的是,一个调用(相同的返回地址)负责4次分配
更奇怪的是:
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa2c
…
@ /usr/java/ibm-java2-x86_64-50/jre/bin/libj9prt23.so:[0x2b270a384a34] + 0x2aaab43a1700 0xa80
在这两行之间,永远不会释放块0x2AAB43A1700
有人知道怎么解释吗?一次调用怎么可能导致4次分配?malloc如何返回以前分配的地址
编辑2008/09/30:
GLIBC(mtrace.pl)提供的用于分析mtrace()输出的脚本在这里没有任何帮助。它只会说:Alloc 0x2aab43a1700 replicate。但是这是怎么发生的呢?一种可能的解释是,同一个函数分配不同的缓冲区大小?其中一个例子就是strdup 对于第二个问题,运行时可能正在分配一些“静态”暂存区域,在进程终止之前不打算释放这些区域。在这一点上,操作系统将在进程结束后进行清理
这样想:在Java中,没有析构函数,也不能保证任何对象都会被调用终结。尝试在valgrind下运行应用程序。它可能会让您更好地了解实际泄漏的内容。您看到的是mtrace的直接输出,这极为混乱且违反直觉。幸运的是,有一个perl脚本(称为mtrace,可以在glibc utils中找到),它可以非常轻松地帮助解析此输出 在调试的情况下编译生成,并像这样运行mtrace:
$ gcc -g -o test test.c
$ MALLOC_TRACE=mtrace.out ./test
$ mtrace test mtrace.out
Memory not freed:
-----------------
Address Size Caller
0x094d9378 0x400 at test.c:6
输出应该更容易理解。分配内存的函数被多次调用。调用方地址指向执行分配的代码,该代码只是被多次运行 下面是C语言中的一个示例:
void *allocate (void)
{
return (malloc(1000));
}
int main()
{
mtrace();
allocate();
allocate();
}
mtrace的输出为:
Memory not freed:
-----------------
Address Size Caller
0x0000000000601460 0x3e8 at 0x4004f6
0x0000000000601850 0x3e8 at 0x4004f6
内存未释放:
-----------------
地址大小调用者
0x4004f6处的0x00000000000601460 0x3e8
0x4004f6处的0x00000000000601850 0x3e8
注意呼叫者地址是如何相同的?这就是为什么mtrace分析脚本说它们是相同的,因为同一个bug被多次看到,从而导致多个内存泄漏
使用调试标志(-g)编译非常有用,如果您可以:
Memory not freed:
-----------------
Address Size Caller
0x0000000000601460 0x3e8 at /home/andrjohn/development/playground/test.c:6
0x0000000000601850 0x3e8 at /home/andrjohn/development/playground/test.c:6
内存未释放:
-----------------
地址大小调用者
0x0000000000610460 0x3e8 at/home/andrjohn/development/played/test.c:6
0x00000000000601850 0x3e8 at/home/andrjohn/development/Played/test.c:6
它不仅是一个函数多次调用malloc(),而且实际上是一个对malloc/realloc/calloc的调用,因为返回地址是相同的。如果运行时正在分配scratch区域,为什么它返回指向该区域的指针是第二个malloc()的结果?我的经验是:valgrind不喜欢java。很容易崩溃,我已经查过了。它将为我提供与skcript:Alloc X duplicate相同的输出。