如何在gdb中设置条件断点,当malloc返回NULL时触发

7

样例源代码:

#include        <stdio.h>
#include        <stdlib.h>
#include        <errno.h>

#define         GIGABYTE        1024*1024*1024

int
main (void)
{
        void    *foo;
        int     result;

        foo = (void *) malloc (GIGABYTE*5);
        result = errno;

        if (foo != NULL) {
                return 2;
        } else {
                fprintf (stderr, "ERROR: %d\n", result);
                return 1;
        }
        return 0;
}

问题:

  • 如何指示gdb (# gdb -silent ./huge_malloc) 在malloc()返回0x0停止/暂停执行,而不需要检查foo是否为0x0

你能解释一下你想做什么吗(特别是为什么要区分malloc的返回值和foo的结果值)? - NPE
简单来说,每当malloc()返回NULL时就使用'break' - 上面的源代码只是一个例子。变量名(在这种情况下为foo)可能会被命名为其他名称。 - Aaron
1
作为一种解决方法,也许你可以在 malloc() 上打断点,然后使用命令列表首先退出 malloc(),然后有条件地继续,如果 $eax != 0 - Georg Fritzsche
@Georg:如何通过gdb实现这个? - Aaron
1
只是一个想法,我还没有尝试过,但可以看看这里:http://sourceware.org/gdb/current/onlinedocs/gdb/Break-Commands.html#Break-Commands。 - Georg Fritzsche
2个回答

7
你可以识别malloc的退出点并在那里设置条件断点。例如:
(gdb) tbreak main
Breakpoint 1 at 0x4005c4: file t.c, line 13.
(gdb) r
Starting program: /var/tmp/a.out 
main () at t.c:13
13          foo = malloc (64);
(gdb) br *__libc_malloc+211 if $rax==0
Breakpoint 2 at 0x7f26d143ea93
(gdb) n
14          foo = malloc (GIGABYTE*64);
(gdb) p foo
$1 = (void *) 0x21dc010
(gdb) n

Breakpoint 2, 0x00007f26d143ea93 in malloc () from /lib/libc.so.6

注意,我添加了一个成功的malloc调用,以说明断点仅在NULL返回值时触发。断点地址可能因libc版本而异,我通过使用nexti逐步操作malloc直到遇到ret指令找到了它。


2

你是否可以编写一个包装器来保存malloc的返回值,然后在该值上设置条件断点?


很遗憾,这是不可能的。上面的源代码只是一个示例 - 我无法更改源代码。 - Aaron
@Aaron:但是你可以将malloc定义为mymalloc(使用-D),强制包含所有源文件所需的头文件,对吧? - Georg Fritzsche
1
@Aaron:GNU ld 有一个 -wrap 标志对于这种情况非常有用,不需要重新编译其他源文件来适应包装器。 - Hasturkun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接