我正在尝试调试内存泄漏问题。我正在使用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:[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
在这两行之间,块0x2aaab43a1700永远不会被释放。
有谁知道如何解释这个?一次调用如何导致4次分配?并且malloc如何返回之前已经分配的地址?
编辑2008/09/30: 分析GLIBC(mtrace.pl)提供的mtrace()输出的脚本在这里没有任何帮助。它只会说:Alloc 0x2aaab43a1700重复。但这怎么可能发生呢?
答案 0 :(得分:8)
你正在研究mtrace的直接输出,这是非常令人困惑和违反直觉的。幸运的是,有一个perl脚本(在glibc-utils中可以找到mtrace),它可以很容易地帮助解析这个输出。
使用调试编译构建,并运行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
输出应该是 lot 更容易消化。
答案 1 :(得分:5)
正在多次调用分配内存的函数。调用者地址指向执行分配的代码,并且该代码只是多次运行。
这是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
请注意来电者地址是如何相同的?这就是为什么mtrace分析脚本说它们是相同的,因为同样的错误被多次看到,导致几次内存泄漏。
如果可以:
,使用调试标志(-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
答案 2 :(得分:0)
一种可能的解释是,相同的功能是分配不同的缓冲区大小?其中一个例子是strdup。
对于第二个问题,运行时可能正在分配一些“静态”临时区域,该区域在进程终止之前不会被释放。此时,操作系统将在此过程后进行清理。
以这种方式思考:在Java中,没有析构函数,也不保证将为任何对象调用终结。
答案 3 :(得分:0)
尝试在valgrind下运行您的应用。它可能会让您更好地了解实际泄露的内容。