segfault:如何知道导致此段错误的行代码或函数

时间:2014-01-06 16:00:53

标签: c linux openwrt

在openwrt设备中执行我的程序时,我收到消息

prog[876]: segfault at 3000747a0 ip 08052d3f sp bfca6a0c error 4 prog[8048000+f000]

我的目的是知道导致此段错误的行代码或函数

可以从消息获取该消息吗?或者如果有其他方法可以做到这一点?

1 个答案:

答案 0 :(得分:1)

正如评论中所提到的,使用调试符号进行编译并在以后的核心转储上运行gdb是获取所需信息的一种方法。如果您熟悉gdb,则使用它是一种通用,快速且直接的方式来查找与segfault消息中给出的位置相对应的代码,特别是如果该位置在您的代码中而不是在库中。

以下是您可以使用的替代方法,以防您不熟悉gdb。对于此替代方案,您需要输出控制台或日志设备;我认为您的OpenWrt嵌入式设备可以使用其中一个。

使用以下行创建头文件,或将其添加到现有头文件中:

#define z fprintf(stderr,"%s@%3d \n",__FILE__,__LINE__);

注意,如果您使用z作为变量名称,请将标识符z替换为其他一些短标识符(例如Zocry等)你的代码。如果合适,请将fprintf替换为syslog。在行尾使用分号会减少每行使用一个字符所需的输入。

将行放在您#include的任何可疑代码文件的头文件中后,在几个函数的开头附近添加字符z(或您选择的任何短标识符)在前面一行代码,然后编译并运行代码。当代码执行并遇到z代码时,它将打印出当前文件和当前行号。每次运行都会缩小可疑范围的代码,您可以从该范围之外删除一些z,并在可疑范围内更加密集地添加z代码。

如果段错误是由于覆盖内存(例如堆栈或堆的一部分),则添加任何调试代码(如上所述)会无法预测地移动问题所在的位置。在这种情况下,您可以回退到gdb。但是,有时向z宏添加更多代码可能会有所帮助,例如打印出相关的任何全局变量的值,或测试某些内存范围是否仍满足某些有效性标准或测试一些变量已经改变了价值。例如:

#define z fprintf(stderr,"%s@%3d \n",__FILE__,__LINE__); testfvalid();
#define z fprintf(stderr,"%s@%3d %d %p  %d %d\n",__FILE__,__LINE__, i, fde+i, fde[i].path, fde[i].name);