gdb

使用 GDB 进行调试

习惯了比GUI的还爽

Posted by 叉叉敌 on May 12, 2022

经常我们使用的vscode、pycharm等等ide,都带有断点设置,参数检查等,但是GDB就没有这些,那我们能不能通过设置,把gdb用起来更简单喃? 比如,如果你知道这些的话,可以跳过了.

  1. gdb 脚本配合–batch
  2. gdb .gdbinit 文件

使用 GDB 进行调试

在过去的几年里,我大部分时间都在用 Python 工作,而且我非常喜欢用 Python 进行调试。您只需将断点()函数调用放入代码中的某个位置,然后将其重新放入程序。我想看看在 c 语言中,我能接近到什么程度。由于 c 语言不是直译语言,我的期望不是很高,但是结果证明用 c 语言调试是相当舒服的。作为奖励,您可以使用 GDB 不仅调试 c 和 c + + ,还可以调试 Rust、 Nim,可能还有任何 C-ABI 的语言。

GDB 基础

首先,我们需要一个程序来调试:

// program.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void print_product(int a, int b) {
    int product = a * b;
    printf("Product: %d\n", product);
}

void print_arguments(int argc, char **argv) {
    for (int i = 1; i < argc; i++) {
        printf("%s ", argv[i]);
    }
    printf("\n");
}

int main(int argc, char **argv) {
    print_arguments(argc, argv);
    srand(time(NULL));
    for (int i = 0; i < 10; i++) {
        print_product(rand(), rand());
    }
    return 0;
}

要调试程序,包含调试符号非常重要。使用 gcc 编译时添加调试符号,请添加 -g 标志。所以让我们编译这个程序:

gcc -g -o program program.c

现在我们可以通过运行以下命令来调试这个程序:

使用 gdb 脚本

了解GDB脚本功能

https://www.adacore.com/gems/gem-119-gdb-scripting-part-1

https://www.adacore.com/gems/gem-120-gdb-scripting-part-2

但这仍然不是很好,现在我们必须在重新启动调试会话时反复输入所有断点。但是有一种方法可以解决这个问题: gdb 脚本。如果使用-x 选项调用 gdb,则可以传递一个包含 gdb 命令的文件给它,它应该执行这个文件。

现在我们可以将断点写入脚本,例如。

现在,我们的断点被存储了。但是还有更多的原因。通常我想检查一些变量。目前希望看到所有循环的乘积变量的值,而不关心其余的:

# gdbscript
b 6
commands
    p product
    c
end

run

然后用这样的--batch运行 gdb:

gdb -x gdbscript program --batch

现在,gdb 将快速打印出所有迭代的产品值,然后再次退出。断点后的命令语句将在命中断点后执行所有包含的命令。最后一个命令 c 表示 continue 并将继续程序流,直到命中下一个断点,一旦上次命中了断点,gdb 将通过 – batch 参数结束执行。

另一个很酷的例子: 让我们假设,不管出于什么原因,我们只对 print_ product() 的第三次调用中的product的值感兴趣。(这当然很傻,因为程序无论如何都会打印它,但在现实调试中,可能会出现这种情况)

set $n = 0

b 6
commands
    set $n = $n + 1
    if $n == 3
        printf "Product is: %d\n", product
    else
        c
    end
end

run

正如您所看到的,我们定义了一个变量 $n,并使用它来计数,然后在第三轮中打印所需的信息。第三轮之后,gdb 会自动退出,退出的原因是 – batch。

.gdbinit 文件

有一个脚本,如果它存在,gdb 将始终隐式加载它: ~/.gdbinit ,你可以把你经常使用的函数放在那里,或者配置。我的是这样的:

set width 0
set height 0
set print pretty on
set confirm off

设置 width 和 height 为0,将防止 gdb 分页长输出,第三行使 gdb 美化输出,最后一行防止它询问我们是否真的想退出。

总结

经常我们使用的vscode、pycharm等等ide,都带有断点设置,参数检查等,但是对于gdb来说就没有GUI来设置这些东西了,难免有点不习惯,但是对于经常使用linux开发者的用户来说,掌握gdb是一个必须的技能。下面这个命令,可以简单地将它们附加到调试器调用中:

gdb -x gdbscript --batch --args program --flags and some args

此外,如果您需要更复杂的调试设置,例如,因为您还必须启动其他程序,那么可以将所有这些组合在一个 shell 脚本中。

当然,还有很多关于 gdb 的内容需要了解,而这仅仅是一个介绍。

Read more

https://www.adacore.com/gems/gem-119-gdb-scripting-part-1

https://felix-knorr.net/posts/2022-02-27-direct-gdb.html

github博客 微信公众号:chasays, 欢迎关注一起吹牛逼,也可以加微信号「xiaorik」互吹。