c - 修复异常原因后 GDB 恢复执行
问题描述
假设我有一个程序,在第 5 行有一个语句,它创建了一个算术异常:除以零。
当我run
在 GDB 中执行程序时,我得到如下信息:
Program received signal SIGFPE, Arithmetic exception.
0x... in ... at prog.c:5
那时,我将除数变量更改为非零值
set var b=1
,然后尝试从出现异常的同一语句中“恢复”。
使用该命令continue
给出以下信息:
Program terminated with signal SIGFPE, Arithmetic exception.
The program no longer exists.
所以正确的方法是使用(而不是continue
命令)一个像jump 5
预期一样工作的命令。
是否有任何其他更简单的 GDB 命令来执行此操作而无需指定程序出现异常的行号?一行中可能有多个语句,因此使用行号寻址并非总是可行的。
我在 GDB 文档中找不到与此相关的任何内容。
解决方案
这种方法在一般情况下不起作用,特别是在优化开启的情况下。
您所做的恰好适用于您的特定线路/案例。我们不能说太多,因为您没有发布代码。
变量b
在内存中开始(在堆栈上或在全局内存中)。
在某些时候,它可能会出现在一个 FP 寄存器中(例如对于 x86,xmm*
)。
所以,当你这样做时:set var b = 1
你是在设置内存位置还是xmm
寄存器?
即使假设每行只有一个语句,当你jump
重新启动语句时(它可以包含多个 asm指令)。
我们还需要做些什么来确保所有其他值(寄存器、内存等)都处于语句前/指令前状态?
通过优化, 的值b
可能已由先前xmm
的语句缓存在寄存器中,而您正在执行的操作可能不会重新加载它 [从内存]jump
您要做的是重新启动指令。此时,指令的第二个参数可能是xmm
寄存器或内存位置。我们怎么知道是哪一个?
此外,如果您有(例如):
a = get_a_value();
// several more statements ...
a /= b; // line 5
然后,我们假设a
is in (eg) xmm0
[and b
is in xmm1
]。以下是伪asm:
fdiv %xmm0,%xmm1 // a /= b
[pseudo]fdiv
指令对a
in的值有什么作用%xmm0
?指令之后的值a
仍然是完整的还是%xmm0
现在有一个部分/垃圾值?%xmm0
失败指令之后的值取决于体系结构。如果值被丢弃,我们如何确定要放回的原始/正确值%xmm0
?
必须执行多少先前a
的语句才能恢复 的正确值?
您可能必须反汇编“违规”指令并更改第二个参数的值。如果它是一个内存位置,请更改它。如果它是一个xmm*
寄存器,你将不得不改变它。
而且,您必须确定必须做什么才能恢复a
价值(无论它位于何处)。
您想要进行的修复需要在指令级别进行处理。语句级别太粗粒度。
您找不到有关此文档的原因是,您所做的在一般情况下不会很好地工作并且正在扭曲gdb
。
gdb
旨在让您可以捕获此类异常,确定程序中的错误是什么,修复源代码,重新构建并重新运行。
C [和/或机器代码] 的设计不允许像 Java/Perl/Python 之类的解释语言那样,允许从之前的点 [在调试器控制台中] 进行动态补丁和重新启动。
推荐阅读
- excel - 在一行中剪切一定范围并在同一行下方插入
- npm - 库依赖项(纱线,npm ...)是否使用 package.json 上的版本字段?
- android - 使用 Intent 服务在 android 中进行后台处理
- python - 你如何在两个不同的多维字典中计算值?
- java - 如何优化我的代码以删除空格和特殊字符?
- java - @Test 中的 Assert 和 SoftAssert 错误
- c# - EF 6 中的可选一对一关系
- mysql - 如何使用联合从表中选择记录,以便第一个查询的结果将每个结果与第二个查询的相应结果连接起来?
- mysql - 在 Golang 中从 MySql 中读取 Json 数据?
- python - python继承类具体练习