您的位置:首页 > 其它

Segment Fault(core dumped)

2015-08-02 15:49 375 查看
最近,写一个二叉树的创建和遍历程序,可以通过编译,但运行时产生了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出错的原因主要是数组访问越界、缓存区溢出、指令走飞,对系统/核心进程造成无法恢复的错误。走飞是指代码走到某一步时,跳转到一些不属于它的指令位置去执行一些莫名其妙的东西。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  segment fault