像Valgrind这样的内存泄漏检查器如何识别免费

时间:2012-07-19 23:20:54

标签: debugging memory-management memory-leaks

我想了解内存泄漏检查程序如何识别是否已为某个给定的malloc调用了free。 malloc可以很容易地通过brk系统调用来识别,所以如果我正在编写一个分析器并单独踩一个在系统调用中断的进程,我就可以很容易地理解malloc已经完成了。 我怎么能找到这个malloc是否已经被要求免费?

以下是strace的输出。这段代码是免费的,我们如何判断是否通过检查此strace来调用free -

read(0, "13608\n", 4096)                = 6
brk(0)                                  = 0x8cc6000
brk(0x8ce7000)                          = 0x8ce7000
write(1, "File name - /proc/13608/maps\n", 29) = 29
open("/proc/13608/maps", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x55559000
read(3, "00349000-00363000 r-xp 00000000 "..., 4096) = 1046
write(1, "ptr1-ffd1f49a\n", 14)         = 14
write(1, "ptr2-ffd1f4a8\n", 14)         = 14
write(1, "Buffer read - 00349000-00363000 "..., 102) = 102
write(1, "\n", 1)                       = 1
write(1, "ptr1-ffd1f49a\n", 14)         = 14
write(1, "ptr2-ffd1f4aa\n", 14)         = 14
write(1, "Buffer read - 00367000-004a6000 "..., 104) = 104
write(1, "\n", 1)                       = 1
write(1, "ptr1-ffd1f49a\n", 14)         = 14
write(1, "ptr2-ffd1f4bd\n", 14)         = 14
write(1, "Buffer read - 08048000-08049000 "..., 123) = 123
write(1, "\n", 1)                       = 1
write(1, "ptr1-ffd1f49a\n", 14)         = 14
write(1, "ptr2-ffd1f4a1\n", 14)         = 14
write(1, "Buffer read - ffad8000-ffaf1000 "..., 95) = 95
write(1, "\n", 1)                       = 1
write(1, "ptr1-ffd1f479\n", 14)         = 14
write(1, "ptr2-ffd1f479\n", 14)         = 14
write(1, "Buffer read - ffffe000-fffff000 "..., 55) = 55
write(1, "\n", 1)                       = 1
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0x55559000, 4096)                = 0
write(1, "Starting Address - 00349000\n", 28) = 28
write(1, "Ending Address - 00363000\n", 26) = 26
write(1, "Permissions - r-xp\n", 19)    = 19
write(1, "Offset - 00000000\n", 18)     = 18
write(1, "PathName - </lib/ld-2.5.so>\n", 28) = 28
write(1, "\n", 1)                       = 1
write(1, "\n", 1)                       = 1
write(1, "Starting Address - 00367000\n", 28) = 28
write(1, "Ending Address - 004a6000\n", 26) = 26
write(1, "Permissions - r-xp\n", 19)    = 19
write(1, "Offset - 00000000\n", 18)     = 18
write(1, "PathName - </lib/libc-2.5.so>\n", 30) = 30
write(1, "\n", 1)                       = 1
write(1, "\n", 1)                       = 1
write(1, "Starting Address - 08048000\n", 28) = 28
write(1, "Ending Address - 08049000\n", 26) = 26
write(1, "Permissions - r-xp\n", 19)    = 19
write(1, "Offset - 00000000\n", 18)     = 18
write(1, "PathName - </fs_user/samirba/myP"..., 49) = 49
write(1, "\n", 1)                       = 1
write(1, "\n", 1)                       = 1
write(1, "Starting Address - ffad8000\n", 28) = 28
write(1, "Ending Address - ffaf1000\n", 26) = 26
write(1, "Permissions - rw-p\n", 19)    = 19
write(1, "Offset - 7ffffffe6000\n", 22) = 22
write(1, "PathName - <[stack]>\n", 21)  = 21
write(1, "\n", 1)                       = 1
write(1, "\n", 1)                       = 1
write(1, "Starting Address - ffffe000\n", 28) = 28
write(1, "Ending Address - fffff000\n", 26) = 26
write(1, "Permissions - r-xp\n", 19)    = 19
write(1, "Offset - ffffe000\n", 18)     = 18
write(1, "PathName - <EMPTY>\n", 19)    = 19
write(1, "\n", 1)                       = 1
write(1, "\n", 1)                       = 1
exit_group(0)                           = ?

2 个答案:

答案 0 :(得分:1)

malloc调用和系统调用之间没有一对一的关系。 通常,malloc库将从操作系统中获得大块 使用例如brk系统调用或mmap系统调用。 然后将这些大块切割成较小的块来服务 连续的malloc调用。免费通常不会导致系统调用 (例如munmap)被调用。 因此,您无法在系统调用级别跟踪malloc和free。

Valgrind可以跟踪内存泄漏,因为它拦截(并替换) malloc,免费,... Valgrind替换函数维护一个已分配块的列表。

真正的泄漏(即不再能够到达的内存,即指向它的所有指针) Valgrind使用所有活动的扫描发现丢失/删除了 存储器中。

答案 1 :(得分:0)

AFAIK,OS分配的内存块由起始地址标识。因此,请查找使用相同参数调用的free(),该参数之前由malloc()返回。当strace记录更多低级mmapbrk次调用时,请使用ltrace记录高级库调用,并注意返回值和参数。