1

我想了解内存泄漏检查器如何识别是否为给定的 malloc 调用了 free。malloc 可以通过 brk 系统调用轻松识别,因此,如果我正在编写分析器并在系统调用中断的进程上执行单步操作,我可以很容易地理解 malloc 已经完成。我如何才能找到这个 malloc 是否已调用免费?

下面是 strace 的输出。这段代码有 free,我们如何通过检查这个 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)                           = ?
4

2 回答 2

1

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

Valgrind 可以跟踪内存泄漏,因为它拦截(和替换)malloc、free、...... Valgrind 替换函数正在维护分配块的列表。

Valgrind 通过扫描所有活动内存来发现真正的泄漏(即无法再访问的内存,即所有指向它的指针都已丢失/擦除)。

于 2012-07-20T23:29:39.953 回答
0

AFAIK,操作系统分配的内存块由起始地址标识。因此,查找free()使用相同参数调用的方法,该参数由malloc()先前返回。随着strace记录更多低级mmapbrk调用,用于ltrace记录高级库调用,密切关注返回值和参数。

于 2012-07-19T23:24:43.433 回答