Segment Fault(core dumped)
2015-08-02 15:49
375 查看
最近,写一个二叉树的创建和遍历程序,可以通过编译,但运行时产生了Segment Fault错误。原程序如下:
查找出错源可以gdb一步步调试,对于小程序可行,几万行代码就受不了了。因此,改用core file。core file是内核转储文件,最大的优点是能够保存问题发生时的状态,哪怕现场不在,也可以用来在对应的执行文件的基础上调试。系统默认core file的文件大小为0,这也是执行出错却没生成core file的原因。利用以下文件或命令修改core file的文件属性:
ulimit -c unlimited(设置core文件大小无限大)
sysctl -a | grep core(查看系统跟core file相关的配置和参数)
sysctl -w kernel.core_pattern=core.%p(core文件名带pid后缀)
需要注意的是/proc/sys/kernel/core_uses_pid能控制产生的core文件的文件名中是否添加pid作为扩展;/proc/sys/kernel/core_pattern能设置格式化的core文件保存位置或文件名。
使用gdb 可执行文件 core file查看错误出在哪一行。
图片显示错误源于 BiTree[i]->lchild=BiTree[2*i+1];
其中显示的地址0x00000000004008d5是汇编代码中的该句所在的寄存器地址。查看可执行文件的反汇编代码有以下步骤:
vim -b 可执行文件(打开二进制的可执行文件)
:%!xxd(可执行文件变成16进制的,其中,:在vim的最后一行显示,%是本文件,!强制执行外部命令)
输入:%!objdump -S -M intel 可执行文件(使用objdump工具查看可执行文件的反汇编代码,由于汇编描述的是CPU的指令,如今比较常用的是Intel、AMD的CPU)
根据分析可知,BiTree数组的下标越界了,数组成员超过了定义的个数后,系统会为多余的成员分配不是此进程的内存,但是不能读取该内存里的内容。改成:
结果正确。
Segment Fault出错的原因主要是数组访问越界、缓存区溢出、指令走飞,对系统/核心进程造成无法恢复的错误。走飞是指代码走到某一步时,跳转到一些不属于它的指令位置去执行一些莫名其妙的东西。
struct NODE{ NODE *lchild, *rchild; int data; }; NODE* CreateNode(int i) { NODE *newnode=new NODE; newnode->data = i; newnode->lchild=NULL; newnode->rchild=NULL; return newnode; } NODE* CreateBiTree() { NODE *BiTree[TREE_SIZE]={NULL}; for(int i=0; i<TREE_SIZE; i++) BiTree[i] = CreateNode(i); for(int i=0; i<= TREE_SIZE; i++) { BiTree[i]->lchild=BiTree[2*i+1]; BiTree[i]->rchild=BiTree[2*i+2]; } return BiTree[0]; } void Postorder(NODE* root) { if(root==NULL) return; Postorder(root->lchild); Postorder(root->rchild); cout<<root->data<<" "; } int main() { NODE *root; root=CreateBiTree(); printf("Post-order is---"); Postorder(root); return 0; }
查找出错源可以gdb一步步调试,对于小程序可行,几万行代码就受不了了。因此,改用core file。core file是内核转储文件,最大的优点是能够保存问题发生时的状态,哪怕现场不在,也可以用来在对应的执行文件的基础上调试。系统默认core file的文件大小为0,这也是执行出错却没生成core file的原因。利用以下文件或命令修改core file的文件属性:
ulimit -c unlimited(设置core文件大小无限大)
sysctl -a | grep core(查看系统跟core file相关的配置和参数)
sysctl -w kernel.core_pattern=core.%p(core文件名带pid后缀)
需要注意的是/proc/sys/kernel/core_uses_pid能控制产生的core文件的文件名中是否添加pid作为扩展;/proc/sys/kernel/core_pattern能设置格式化的core文件保存位置或文件名。
使用gdb 可执行文件 core file查看错误出在哪一行。
图片显示错误源于 BiTree[i]->lchild=BiTree[2*i+1];
其中显示的地址0x00000000004008d5是汇编代码中的该句所在的寄存器地址。查看可执行文件的反汇编代码有以下步骤:
vim -b 可执行文件(打开二进制的可执行文件)
:%!xxd(可执行文件变成16进制的,其中,:在vim的最后一行显示,%是本文件,!强制执行外部命令)
输入:%!objdump -S -M intel 可执行文件(使用objdump工具查看可执行文件的反汇编代码,由于汇编描述的是CPU的指令,如今比较常用的是Intel、AMD的CPU)
根据分析可知,BiTree数组的下标越界了,数组成员超过了定义的个数后,系统会为多余的成员分配不是此进程的内存,但是不能读取该内存里的内容。改成:
for(int i=0; i<= (TREE_SIZE/2-1); i++) { BiTree[i]->lchild=BiTree[2*i+1]; BiTree[i]->rchild=BiTree[2*i+2]; }
结果正确。
Segment Fault出错的原因主要是数组访问越界、缓存区溢出、指令走飞,对系统/核心进程造成无法恢复的错误。走飞是指代码走到某一步时,跳转到一些不属于它的指令位置去执行一些莫名其妙的东西。
相关文章推荐
- 关于Segmentation fault (core dumped)
- Oracle 11gR2 延迟段创建
- 造成segment fault,产生core dump的可能原因
- 利润中心段更改
- C语言数组与指针
- Oracle手工生成段建议(Segment Advisor)
- 分段控件/segment
- 回收段空间
- [Oracle] Lob介绍
- Linux环境下段错误的产生原因及调试方法小结
- Segmentation fault到底是何方妖孽
- segamentation falut:free a pointer mutiple times
- C/C++中的段错误(Segmentation fault)
- iOS中各种控件的使用
- oracle 11gR2 创建无数据对象临时不分配segment
- Segment
- UISegmentedControl控件
- MATROSKA文件格式之Segments学习
- ceph: how to fix if monitor IP changes
- C中Segmentation fault的总结