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
应该是一个 bool
和 static
生命周期,它指定观察点是否应该处于活动状态。
每当您想为 intended_value
和 actual_value
分配一个新值时,您可以将 enable_break
设置为 false
,将两个变量都设置为新值,然后然后通过将 enable_break
设置为 true
来重新启用观察点。这样,当您有意为这些变量分配新值时,观察点将永远不会触发。
但是请注意,根据 GDB documentation on watchpoints,软件观察点可能无法检测到另一个线程是否更改了观察点的表达式。
在 Linux 上,调试此类问题的最佳 方法是使用可逆调试器,例如 rr.
它允许您例如运行 直到崩溃或损坏,然后设置观察点并执行 reverse-cont
返回到上次更新值的位置。
这适用于你的情况——损坏是可重复的,也在随机内存损坏的情况下——因为rr
重播运行 完全,反向执行时没有变化。
我有一个 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
应该是一个 bool
和 static
生命周期,它指定观察点是否应该处于活动状态。
每当您想为 intended_value
和 actual_value
分配一个新值时,您可以将 enable_break
设置为 false
,将两个变量都设置为新值,然后然后通过将 enable_break
设置为 true
来重新启用观察点。这样,当您有意为这些变量分配新值时,观察点将永远不会触发。
但是请注意,根据 GDB documentation on watchpoints,软件观察点可能无法检测到另一个线程是否更改了观察点的表达式。
在 Linux 上,调试此类问题的最佳 方法是使用可逆调试器,例如 rr.
它允许您例如运行 直到崩溃或损坏,然后设置观察点并执行 reverse-cont
返回到上次更新值的位置。
这适用于你的情况——损坏是可重复的,也在随机内存损坏的情况下——因为rr
重播运行 完全,反向执行时没有变化。