gdb:获取值的最后更改

gdb: Get last changes of value

我有一个 C 应用程序有一个错误:有一个值(在静态数组中的特定位置;所以地址是众所周知的)在某个时候有一个意外的值。我试过这些东西:

一旦值为“意外”,应用程序就会挂起(基本上自旋锁会永远循环)。如果发生这种情况,我想获取特定地址的最后更改。

是否可以用 gdb 做到这一点?

非常感谢

-编辑-

在值更改时始终转储堆栈跟踪并自动继续就已经足够了。我不确定使用 gdb 是否可以轻松做到这一点。

Using watch-point: Unfortunately the value can change many many times in a valid way until the change is invalid. Even the final value might an will appear many times (which is valid). So it's not possible to check for a specific value.

GDB 观察点不仅支持在特定内存地址的值更改为特定值时中断。它还支持更复杂的条件表达式,例如:

enable_break && intended_value != actual_value

在评论部分,您声明预期的更改是微不足道的,并且您确定该值是从非预期来源修改的。因此,如果 actual_value 是从意外来源修改的值,那么您可以引入一个生命周期为 static 的新变量,称为 intended_value,您将其设置为与 actual_value 每当您有意更改此变量的值时。

但是,使用表达式

intended_value != actual_value

单独使用会出现无法同时为两个变量设置新值的问题,并且一个接一个地修改变量会触发观察点。

为了防止在更改这些变量的值时触发观察点,可以将表达式更改为以下内容:

enable_break && intended_value != actual_value

变量 enable_break 应该是一个 boolstatic 生命周期,它指定观察点是否应该处于活动状态。

每当您想为 intended_valueactual_value 分配一个新值时,您可以将 enable_break 设置为 false,将两个变量都设置为新值,然后然后通过将 enable_break 设置为 true 来重新启用观察点。这样,当您有意为这些变量分配新值时,观察点将永远不会触发。

但是请注意,根据 GDB documentation on watchpoints,软件观察点可能无法检测到另一个线程是否更改了观察点的表达式。

在 Linux 上,调试此类问题的最佳 方法是使用可逆调试器,例如 rr.

它允许您例如运行 直到崩溃或损坏,然后设置观察点并执行 reverse-cont 返回到上次更新值的位置。

这适用于你的情况——损坏是可重复的,在随机内存损坏的情况下——因为rr重播运行 完全,反向执行时没有变化。