我有一个C++应用程序,经过交叉编译适用于在ARM CortexA9处理器上运行的Linux系统。该应用程序出现了SIGFPE/算术异常导致崩溃的问题。一开始我认为这可能是由于gcc的-O3优化标志引起的,但后来我在调试模式下构建它,还是会崩溃。
我使用gdb调试应用程序,捕获了异常,但不幸的是触发异常的操作似乎也破坏了堆栈,所以我无法获取有关导致异常的代码位置的详细信息。最后我唯一能够得到的细节是触发异常的操作(从以下堆栈跟踪片段中获得):
3 raise() 0x402720ac
2 __aeabi_uldivmod() 0x400bb0b8
1 __divsi3() 0x400b9880
__aeabi_uldivmod()是执行无符号长长除法和取模运算的函数,我尝试了粗暴的方法,搜索可能使用该操作的代码,但没有取得什么成果,因为这证明是一项艰巨的任务。此外,我尝试检查潜在的零除法,但是由于代码库太大,检查每个除法操作是一种繁琐而愚蠢的方法。因此,必须有更聪明的方法来找出问题所在。在调试器无法提供帮助的情况下,是否有任何技术可以追踪这些异常的原因? 更新: 在处理十六进制数、转储内存并进行堆栈取证(感谢Crashworks)后,我在ARM编译器文档中发现了这个宝石(尽管我没有使用ARM Ltd.编译器):
整数除以零错误可以通过重新实现相应的C库帮助程序来捕获和标识。 当使用信号函数或重新实现 __rt_raise() 或 __aeabi_idiv0() 时, 除以零时的默认行为是调用 __aeabi_idiv0()。 否则,除法函数返回零。 __aeabi_idiv0()会引发SIGFPE,并附带一个参数DIVBYZERO。
因此,我在__aeabi_idiv0(_aeabi_ldiv0)处设置了断点,然后,我在被完全崩溃之前就获得了完整的堆栈跟踪。感谢大家给出的非常有启发性的答案! 免责声明:本“获胜”的答案是根据其对我的调试工作的建议的重要性而单独和主观地选择的,因为不止一个回答是具有信息量并且真正有帮助的。