c – 如何跟踪SIGFPE /算术异常

前端之家收集整理的这篇文章主要介绍了c – 如何跟踪SIGFPE /算术异常前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个交叉编译的C应用程序,用于运行在ARM CortexA9处理器上的 Linux,该处理器与SIGFPE / Arithmetic异常崩溃.最初我以为是因为gcc的-O3标志引入了一些优化,但是我在调​​试模式下构建它,它仍然崩溃.

我用gdb调试了应用程序,捕获异常,但不幸的是,操作触发异常似乎也会垃圾堆栈,所以我无法获得任何关于我的代码中导致发生的地方的详细信息.我可以得到的唯一的细节是触发异常的操作(从以下堆栈跟踪):

3 raise()  0x402720ac   
    2 __aeabi_uldivmod()  0x400bb0b8    
    1 __divsi3()  0x400b9880

__aeabi_uldivmod()正在执行一个无符号的长时间划分和提醒,所以我尝试了强力的方法,并搜索我的代码可能使用该操作的地方,但没有太多的成功,因为它被证明是一个艰巨的任务.此外,我还试图检查潜在的部门为零,但代码基础却相当大,并检查每个部门的操作,这是一个麻烦和有点愚蠢的方法.所以必须有一个更聪明的方式来弄清楚发生了什么.

当调试器无法做很多帮助时,是否有任何技巧来追踪这种异常的原因?

更新:对十六进制数进行处理后,转储内存并进行堆栈取证(谢谢Crashworks)我在ARM编译器文档中遇到了这个gem(即使我没有使用ARM的编译器):

Integer division-by-zero errors can be trapped and identified by
re-implementing the appropriate C library helper functions. The
default behavior when division by zero occurs is that when the signal
function is used,or
__rt_raise() or __aeabi_idiv0() are re-implemented,__aeabi_idiv0() is
called. Otherwise,the division function returns zero.
__aeabi_idiv0() raises SIGFPE with an additional argument,DIVBYZERO.

所以我把一个断点放在__aeabi_idiv0(_aeabi_ldiv0)et Voila !,我完整的堆栈跟踪完全被丢弃.感谢大家的非常翔实的答案!

免责声明:“获奖”答案是单独和主观地考虑到我的调查工作的建议的重量,因为多个信息丰富,真正有用.

解决方法

我的第一个建议是打开一个记忆窗口,看着你的堆栈指针周围的区域,然后挖掘它,看看你是否可以找到附近没有破坏的堆栈框架,这可能会给你一个关于崩溃的地方的线索.通常堆栈垃圾只会烧掉几个堆栈帧,所以如果你看上去几百个字节,你可以通过损坏的区域,并得到代码的一般感觉.你甚至可以往下看堆栈,假设死亡函数在死亡之前可能会调用其他函数,因此内存中可能还存在一个指向当前IP的旧帧.

评论中,我链接了一些演示幻灯片,说明了PowerPC上的技术 – 在类似的故障堆栈崩溃中,查看大约73-86的案例研究.显然,您的ARM的堆栈框架将不同,但一般原则成立.

原文链接:https://www.f2er.com/c/113569.html

猜你在找的C&C++相关文章