调试竞争条件时打印信息的最佳方式

Muf*_*ffo 5 c debugging printf gdb race-condition

我正在调试一个应用程序来修复我怀疑是由竞争条件引起的分段错误。

我想在代码中添加一些打印语句,但我知道printf不建议添加对的调用,因为这可能会改变线程的行为并在某些情况下隐藏错误。

查看其他选项,我已经看到使用gdb可以使用断点打印某些内容,然后自动继续执行:

break foo
commands
silent
printf "Called foo: x is %d\n",x
cont
end
Run Code Online (Sandbox Code Playgroud)

这比printf在我的代码中放入一个更好吗?

我知道gdb也有一个跟踪点,但它们只适用于 gdbserver,这是我目前更愿意避免的额外复杂程度。

附加信息:该应用程序是用 C 编写的,可在 Linux 上运行。

Emp*_*ian 5

这比在我的代码中添加 printf 更好吗?

不,情况更糟。GDB 中遇到的每个断点都会触发以下事件链:

  • 从运行线程到 GDB 的上下文切换
  • GDB 停止所有其他线程(假设默认全停止模式)
  • GDB 评估断点命令
  • GDB 恢复所有线程(这本身就是一个复杂的多步骤过程,我不会在这里详细介绍)。

这比简单的调用至少要昂贵一个数量级且具有破坏性printf,并且很可能隐藏您试图调试的任何竞争。

最重要的是,GDB 通常完全不适合调试数据竞争。

我赞同 Christopher Ian Stern 推荐的 ThreadSanitizer。

这个错误的唯一问题是我正在生产机器上进行调试,我无法安装其他软件。

首先,ThreadSanitizer 会检测您现有的程序。它有一个运行时库,但可以静态链接到您的二进制文件中。您无需在生产计算机上安装任何内容。

其次,ThreadSanitizer 会检测数据争用,即使它们不会导致可见的行为变化。很可能您根本不需要在生产计算机上运行:只需在开发计算机上运行测试(您确实有测试,对吧?)可能就足够了。