这段代码一直segmentation fault。哪儿出错了?

而我常用的调试方法有:

1)在程序内部的关键部位输出(printf)信息,那样可以跟踪 段错误 在代码中可能的位置

为了方便使用这种调试方法,可以用条件编译指令#ifdef DEBUG和#endif把printf函数给包含起来,编译的时候加上-DDEBUG参数就可以查看调试信息。反之,不加上该参数进行调试就可以。

2)用gdb来调试,在运行到段错误的地方,会自动停下来并显示出错的行和行号

这个应该是很常用的,如果需要用gdb调试,记得在编译的时候加上-g参数,用来显示调试信息
对于这个,网友在《段错误bug的调试》文章里创造性的使用这样的方法,使得我们在执行程序的时候就可以动态扑获段错误可能出现的位置:
通过扑获SIGSEGV信号来触发系统调用gdb来输出调试信息。
如果加上上面提到的条件编译,那我们就可以非常方便的进行段错误的调试拉。

原来“Segmentation fault“的调试是一个很大的知识点!(!嘿)
,在上面的剪贴中,谈到的《段错误bug的调试》的文章,这里也粘贴过来!

我们在用C/C++语言写程序的时侯,内存管理的绝大部分工作都是需要我们来做的。实际上,内存管理是一个比较繁琐的工作,无论你多高明,经验多丰富,难免会在此处犯些小错误,而通常这些错误又是那么的浅显而易于消除。但是手工“除虫”(debug),往往是效率低下且让人厌烦的,本文将就"段错误"这个内存访问越界的错误谈谈如何快速定位这些"段错误"的语句。
下面将就以下的一个存在段错误的程序介绍几种调试方法:

作为一个熟练的C/C++程序员,以上代码的bug应该是很清楚的,因为它尝试操作地址为0的内存区域,而这个内存区域通常是不可访问的禁区,当然就会出错了。我们尝试编译运行它:

果然不出所料,它出错并退出了。
1.利用gdb逐步查找段错误:
这种方法也是被大众所熟知并广泛采用的方法,首先我们需要一个带有调试信息的可执行程序,所以我们加上“-g -rdynamic"的参数进行编译,然后用gdb调试运行这个新编译的程序,具体步骤如下:

哦?!好像不用一步步调试我们就找到了出错位置d.c文件的第4行,其实就是如此的简单。
从这里我们还发现进程是由于收到了SIGSEGV信号而结束的。通过进一步的查阅文档(man 7 signal),我们知道SIGSEGV默认handler的动作是打印”段错误"的出错信息,并产生Core文件,由此我们又产生了方法二。
Core文件是什么呢?

以上资料摘自man page(man 5 core)。不过奇怪了,我的系统上并没有找到core文件。后来,忆起为了渐少系统上的拉圾文件的数量(本人有些洁癖,这也是我喜欢Gentoo的原因之一),禁止了core文件的生成,查看了以下果真如此,将系统的core文件的大小限制在512K大小,再试:

core文件终于产生了,用gdb调试一下看看吧:

哇,好历害,还是一步就定位到了错误所在地,佩服一下Linux/Unix系统的此类设计。
接着考虑下去,以前用windows系统下的ie的时侯,有时打开某些网页,会出现“运行时错误”,这个时侯如果恰好你的机器上又装有windows的编译器的话,他会弹出来一个对话框,问你是否进行调试,如果你选择是,编译器将被打开,并进入调试状态,开始调试。
Linux下如何做到这些呢?我的大脑飞速地旋转着,有了,让它在SIGSEGV的handler中调用gdb,于是第三个方法又诞生了:
3.段错误时启动调试:

怎么样?是不是依旧很酷?
以上方法都是在系统上有gdb的前提下进行的,如果没有呢?其实glibc为我们提供了此类能够dump栈内容的函数簇,详见/usr/include/execinfo.h(这些函数都没有提供man page,难怪我们找不到),另外你也可以通过 进行学习。

这次你可能有些失望,似乎没能给出足够的信息来标示错误,不急,先看看能分析出来什么吧,用objdump反汇编程序,找到地址0x804876f对应的代码位置:

我们还是找到了在哪个函数(dummy_function)中出错的,信息已然不是很完整,不过有总比没有好的啊!
本文给出了分析"段错误"的几种方法,不要认为这是与孔乙己先生的"回"字四种写法一样的哦,因为每种方法都有其自身的适用范围和适用环境,请酌情使用,或遵医嘱。

哈,现在可以用上面的方法调试一下自己的程序了!

为了方便调试,我把strcat函数也写进来(这里的strcat是自己些的)

//调试说明:编译后第一次调试的结果可能与第二次调试的结果不同。比如,在下面的调试中,当收到SIGSEGV,第一次并不直接结束,等待输入c 命令后才结束。第二次的时候当收到SIGSEGV后程序就终止了!当我再次编译程序后调试又是第一次的结果!甚至当我输入命令p s1的时候,打印的却是s2的内容!

0x40065c的位置(事实表明这个操作并未成功!至于为啥失败,我也纳闷着呢!如果说把“lei”中的l不能放在

0x40065d的位置,这道好理解:缓冲区绝对溢出,并且dest与src重叠!所以我就委屈这样理解了:所谓溢出指的是该空间内已经不能存放一个完整的字符串了!)。

}

一点也不懂...到底是怎么回事了????

怎么办也......不懂,,真的不好也.....问题的是,除了借助网络外,我是一点办法也没有了. ... ...啊...

对了,,想起一个问题,...LINUX和WINDOWS上的SQL连接,,,,这和不同平台上的数据库连接有没有关系...??

但我用不不同平台上连接操作时,,出现上面一样的错误,,,就是没行反映....烦死了..

楼上高手....帮我解决下嘛...

我刚学程序的.. . .才学一学期.....不说这些了.

重装 SQL?你写过 C/C++ 程序没?晕。。。

我的SQL是以WINDOWS身份登录的,,所以也就不要用户名和密码了..

如果这样,,我重装SQL再照你说的做下了..

但运行./a.out时出现上面的错误,,,,请高手指点一下。。。。

从你对这个错误的了解程度可知你对指针还不熟悉
熟悉指针也不是一天两天能完成的

还是贴代码, 让大家看看吧

}

最近写了一个字符反编码的函数,如字符'A'的编码为'41',通过下文中的unhex("41")函数可以直接返回符'A'.在TC中调试可以得到正确的结果,但是在linux下执行的时候一直报"Segmentation fault"的错误,所以麻烦各位帮忙看下原因,多谢!

}

我要回帖

更多关于 电脑运行出错错误代码1 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信