【问题标题】:How to do an specific action when a certain breakpoint is hit in GDB?在 GDB 中命中某个断点时如何执行特定操作?
【发布时间】:2011-06-29 07:56:33
【问题描述】:

我正在寻找一种在 gdb 中遇到特定断点时执行某些操作的方法。

基本上我的程序中有一些内存泄漏。当 malloc 和 free 函数命中时,我需要进入函数(步骤)并收集一些基本信息,如地址和大小(基本上打印那里的值)。完成后恢复我的程序。

我们有什么好的方法吗?

【问题讨论】:

    标签: c gdb


    【解决方案1】:

    例如,当 x 为正时,您可以使用断点命令在 foo 的入口处打印 x 的值。

    break foo if x>0
    commands
    silent
    printf "x is %d\n",x
    cont
    end
    

    如果您在命令列表中指定的第一个命令是silent,则不会打印有关在断点处停止的通常消息。这对于要打印特定消息然后继续的断点可能是可取的。如果其余命令都没有打印任何内容,则您看不到断点已到达的迹象。静默仅在断点命令列表的开头才有意义。

    断点命令的一个应用是补偿一个错误,以便您可以测试另一个错误。在错误的代码行之后放置一个断点,给它一个条件来检测发生错误的情况,并给它命令以将正确的值分配给需要它们的任何变量。以 continue 命令结束,这样您的程序就不会停止,并以静默命令开始,这样就不会产生任何输出。这是一个例子:

    break 403
    commands
    silent
    set x = y + 4
    cont
    end
    

    【讨论】:

    • 谢谢弗雷德里克。但是这里的变量名是未知的。假设我有 1GB 的代码。那么我们需要做什么呢?有没有通用的方法可以做到这一点?
    • 谢谢。 valgrind 将在内存泄漏的情况下帮助我。但总的来说有没有其他方法可以实现。只是为了探索......
    • 你知道如何阻止GDB提示吗?我的意思是那些消息Type <return> to continue, or q <return> to quit---
    【解决方案2】:

    为了澄清 Fredrik 的回答,commands(或者似乎只是 command)自动知道您只是设置了一个断点。也就是说,Fredrik 显示的不是多行 break 命令,而是两个单独的命令:breakcommands。它看起来像这样:

    (gdb) break 989 
    Breakpoint 23 at 0x7fffe2761dac: file foo.cpp, line 989.
    (gdb) command
    Type commands for breakpoint(s) 23, one per line.
    End with a line saying just "end".
    >silent
    >print result
    >end
    (gdb) c
    Continuing.
    $79 = {elems = {0, 0}}
    (gdb) 
    

    【讨论】:

    • command vs commands:GCC 允许你只写命令的前缀,只要它是唯一的。另外,对于其他人:“帮助命令”表明可以指定断点来设置条件。
    【解决方案3】:

    dprintf(动态printf

    https://sourceware.org/gdb/onlinedocs/gdb/Dynamic-Printf.html

    对于打印东西的具体情况,这是最方便的解决方案:

    dprintf <line>, "%u\n", variable
    

    它也可能比commands 更快,因为它可以编译和注入代码,而不是将控制权交还给 GDB 以解释任意命令字符串,这非常慢。 TODO 我不知道这是否真的完成了。 dprintf vs commands: What is the difference between dprintf vs break + commands + continue?

    详细示例:

    main.c

    #include <inttypes.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void) {
        uint32_t i;
        uint32_t r = 0;
        for (i = 0; i < 10; ++i) {
            r += i*i + 13*r*i + 17;   /* LINE 10. */
        }
        printf("%" PRIu32 "\n", r);
        return EXIT_SUCCESS;
    }
    

    然后:

    gcc -ggdb3 -O0 -std=c99 -o main main.c
    gdb -batch --nh -q -ex 'dprintf 10, "%u %u\n", i, r' -ex 'run' ./main
    

    输出:

    Dprintf 1 at 0x400545: file main.c, line 10.
    0 0
    1 17
    2 256
    3 6933
    4 277346
    5 14699371
    6 970158528
    7 3628079733
    8 3070853710
    9 317092431
    3057168588
    [Inferior 1 (process 14305) exited normally]
    

    在 Ubuntu 16.04、GDB 8.2 中测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-23
      • 2015-11-13
      • 2018-12-15
      • 2018-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-01
      相关资源
      最近更新 更多