首页 > 代码库 > Segmentation Fault的一种定位方法
Segmentation Fault的一种定位方法
1. 介绍
网上有很多Segmentation Fault的调试方法,下面这篇文件就很好
<Linux环境下段错误的产生原因及调试方法小结>
然而笔者在实际的使用中由于各种原因总觉得不够用
于是在网上找到了一种个人觉得更直接的方法
2. 原理
Segmentation Fault发生的时候,程序收到了信号11(SIGSEGV)
我们捕获该信号,然后利用事故发生时保存的寄存器现场加上栈信息定位到具体行
这里参考了< C/C++捕获段错误,打印出错的具体位置(精确到哪一行) >
使用其提供的头文件segvCatch.h
3. 实例程序
下面是测试用的实例程序 SegFault.c
1: #include "segvCatch.h"
2:
3: void SegFaultFunc()
4: {
5: int *p = NULL;
6: *p = 123;
7: }
8: void Func3()
9: {
10: SegFaultFunc();
11: }
12: void Func2()
13: {
14: Func3();
15: }
16: void Func1()
17: {
18: Func2();
19: }
20: int main()
21: {
22: initSegvCatch();
23: Func1();
24: return 0;
25: }
4. 分析
下面是编译和定位过程
[Jerry@ work]$ gcc SegFault.c -g -o SegFault -rdynamic[Jerry@ work]$./SegFault signal[11] catched when running code at 80488d6signal[11] catched when running code at 80488b9signal[11] catched when running code at 80488afsignal[11] catched when running code at 80488a5signal[11] catched when running code at 8048896Aborted[Jerry@ work]$ addr2line 80488d6 80488b9 80488af 80488a5 8048896 -e ./SegFault -f main/home/Jerry/work/SegFault.c:23Func1/home/Jerry/work/SegFault.c:18Func2/home/Jerry/work/SegFault.c:14Func3/home/Jerry/work/SegFault.c:10SegFaultFunc/home/Jerry/work/SegFault.c:6<style type="text/css">.csharpcode, .csharpcode pre{ font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em;}.csharpcode .lnum { color: #606060; }</style>
可以看到最后依次显示了调用顺序
main() –> Func1() –> Func2() –> Func3() –> SegFaultFunc()
同时定位到具体出错的行(第六行)
值得注意是在编译时需要加上-g以获得调试信息()
5. 扩展
由于笔者开发使用的系统架构是ARM,而上面的segvCatch.h只支持x86
故笔者在一番研究之后得到了基于ARM和MIPS的方法
关键点在于获取当前执行的指令的地址
对于X86,为EIP寄存器
对于ARM/MIPS,则为PC寄存器
其实际值可以查看工具链头文件ucontext.h来了解实际定义的保存方式
对于X86 为ucontext_t.uc_mcontext.gregs[REG_EIP]对于ARM 为ucontext_t.uc_mcontext.arm_pc对于MIPS 为ucontext_t.uc_mcontext.pc (未测试)
6. 下载
修改后的版本已上传至GitHub
https://github.com/sharmer/SomeDownload/tree/master/SegFault
Segmentation Fault的一种定位方法
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。