使用GDB在malloc和free函数设置断点,并打印分配和释放时的内存地址以及调用栈,然后通过脚本分析分配和释放是否配对来检测是否存在内存泄露以及发生内存泄漏的位置。
mingdu.zheng at gmail dot com
malloc和free的包装,为了方便地设置断点。
#include <stdlib>
void _wrapmalloc_print_addr(const void* addr)
{
(void)addr;
}
void _wrapfree_print_addr(const void* addr)
{
(void)addr;
}
void *wrapmalloc(size_t size)
{
void *p;
p = malloc(size);
if(p)
{
_wrapmalloc_print_addr(p);
}
return p;
}
void wrapfree(const void *p)
{
if(p)
{
_wrapfree_print_addr(p);
}
free((void*)p);
}
自动化脚本,调用GDB,自动输入命令,报告输出到leak.log。
#!/usr/bin/expect -f
set gdb [lindex $argv 0]
set exec [lindex $argv 1]
set target [lindex $argv 2]
set timeout 10000
spawn $gdb $exec -ex $target
expect "(gdb)"
send "monitor reset\r"
expect "(gdb)"
send "load\r"
#expect "(gdb)"
#send "monitor reset\r"
expect "(gdb)"
send "set pagination off\r"
expect "(gdb)"
send "b _wrapmalloc_print_addr\r"
expect "(gdb)"
send "commands\r"
expect ">"
send "silent\r"
expect ">"
send "printf \"malloc,%p\\n\", addr\r"
expect ">"
send "bt 5\r"
expect ">"
send "c\r"
expect ">"
send "end\r"
expect "(gdb)"
send "b _wrapfree_print_addr\r"
expect "(gdb)"
send "commands\r"
expect ">"
send "silent\r"
expect ">"
send "printf \"free,%p\\n\", addr\r"
expect ">"
send "bt 5\r"
expect ">"
send "c\r"
expect ">"
send "end\r"
expect "(gdb)"
send "c\r"
expect eof
exit
内存泄漏分析脚本,检测malloc释放有配对的free,如果没有那么打印该malloc的调用栈,通过调用栈可以找到分配内存的位置。
#!/usr/bin/python
path="leak.log"
t = {}
f = file(path)
l = f.readline()
malloc = False
a = ""
while l != "":
if l.startswith("malloc"):
malloc = True
a = l.split(",")[1]
t[a] = ""
elif l.startswith("free"):
malloc = False
del t[l.split(",")[1]]
else:
if malloc:
t[a] += l
l = f.readline()
for i in t:
print i
print t[i]