C语言系统调试中出现的问题及修改调试失败

c语言程序调试结果为什么会和运行结果不一致
[问题点数:40分,结帖人a]
本版专家分:0
结帖率 100%
CSDN今日推荐
本版专家分:369999
2017年 总版技术专家分年内排行榜第一
2014年 总版技术专家分年内排行榜第二
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
本版专家分:16781
2016年8月优秀小版主优秀小版主2015年7月优秀小版主2015年8月优秀小版主2015年9月优秀小版主2015年5月优秀小版主2015年4月潜水乐园小板版主2015年2月论坛优秀版主2014年11月论坛优秀版主
2015年11月 扩充话题大版内专家分月排行榜第一2015年7月 扩充话题大版内专家分月排行榜第一2015年1月 扩充话题大版内专家分月排行榜第一2014年9月 扩充话题大版内专家分月排行榜第一(补)2013年9月 扩充话题大版内专家分月排行榜第一2013年8月 扩充话题大版内专家分月排行榜第一2013年7月 扩充话题大版内专家分月排行榜第一
2016年3月 扩充话题大版内专家分月排行榜第二2015年12月 扩充话题大版内专家分月排行榜第二2015年6月 扩充话题大版内专家分月排行榜第二2015年2月 扩充话题大版内专家分月排行榜第二2014年10月 扩充话题大版内专家分月排行榜第二2014年8月 扩充话题大版内专家分月排行榜第二
2016年4月 扩充话题大版内专家分月排行榜第三2015年9月 扩充话题大版内专家分月排行榜第三2015年3月 扩充话题大版内专家分月排行榜第三2014年1月 扩充话题大版内专家分月排行榜第三2013年12月 扩充话题大版内专家分月排行榜第三2013年4月 C/C++大版内专家分月排行榜第三
本版专家分:369999
2017年 总版技术专家分年内排行榜第一
2014年 总版技术专家分年内排行榜第二
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
本版专家分:0
本版专家分:0
本版专家分:16781
2016年8月优秀小版主优秀小版主2015年7月优秀小版主2015年8月优秀小版主2015年9月优秀小版主2015年5月优秀小版主2015年4月潜水乐园小板版主2015年2月论坛优秀版主2014年11月论坛优秀版主
2015年11月 扩充话题大版内专家分月排行榜第一2015年7月 扩充话题大版内专家分月排行榜第一2015年1月 扩充话题大版内专家分月排行榜第一2014年9月 扩充话题大版内专家分月排行榜第一(补)2013年9月 扩充话题大版内专家分月排行榜第一2013年8月 扩充话题大版内专家分月排行榜第一2013年7月 扩充话题大版内专家分月排行榜第一
2016年3月 扩充话题大版内专家分月排行榜第二2015年12月 扩充话题大版内专家分月排行榜第二2015年6月 扩充话题大版内专家分月排行榜第二2015年2月 扩充话题大版内专家分月排行榜第二2014年10月 扩充话题大版内专家分月排行榜第二2014年8月 扩充话题大版内专家分月排行榜第二
2016年4月 扩充话题大版内专家分月排行榜第三2015年9月 扩充话题大版内专家分月排行榜第三2015年3月 扩充话题大版内专家分月排行榜第三2014年1月 扩充话题大版内专家分月排行榜第三2013年12月 扩充话题大版内专家分月排行榜第三2013年4月 C/C++大版内专家分月排行榜第三
本版专家分:369999
2017年 总版技术专家分年内排行榜第一
2014年 总版技术专家分年内排行榜第二
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
本版专家分:44590
2018年6月 C/C++大版内专家分月排行榜第二2018年1月 C/C++大版内专家分月排行榜第二2017年12月 C/C++大版内专家分月排行榜第二2017年8月 C/C++大版内专家分月排行榜第二
2018年5月 C/C++大版内专家分月排行榜第三2018年4月 C/C++大版内专家分月排行榜第三2018年3月 C/C++大版内专家分月排行榜第三2018年2月 C/C++大版内专家分月排行榜第三2017年11月 C/C++大版内专家分月排行榜第三2017年10月 C/C++大版内专家分月排行榜第三2017年9月 C/C++大版内专家分月排行榜第三2017年6月 C/C++大版内专家分月排行榜第三2017年5月 C/C++大版内专家分月排行榜第三2017年4月 C/C++大版内专家分月排行榜第三2017年3月 C/C++大版内专家分月排行榜第三
本版专家分:0
本版专家分:0
匿名用户不能发表回复!
其他相关推荐有些时候我们在一段C代码的时候,由于对一个非法内存进行了操作,在程序运行的过程中,出现了"段错误"。
呵呵,这种问题我想很多人会经常遇到。遇到这种问题是非常无语的,只是提示了"段错误",接着什么都没 有,如果我们一味的去看代码找太疼苦了,因为我们都相信自己写的代码没问题,现实就是现实。下面介绍一种方法,可以有效的定位出现"段错误的地方"。
当我们的程序崩溃时,内核有可能把该程序当前内存映射到core文件里,方便程序员找到程序出现问题的地方。
什么是core dump?
core的意思是内存,dump的意思是扔出来,堆出来。
为什么没有core文件生成呢?
有时候程序down了,但是core文件却没有生成.core文件的生成跟你当前系统的环境设置有关系,可以用下面的语句设置一下便生成core文件了
有关ulimit两篇博文:
http://www.cnblogs.com/wangkangluo1/archive//2537677.html
http://www.cnblogs.com/ibook360/archive//2495405.html
core 文件生成的位置一般于运行程序的路径相同,在ubuntu下文件名一般 为core.
什么是core文件
当一个程序奔溃时,在进程当前工作目录的core文件中复制了该进程的存储图像。core文件仅仅是一个内存映像(同时加上调试信息),主要用来调试的。
下面我们来看看,怎样利用core文件来定位我们出现"段错误"的地方.程序运行结果:从上面我们可以看出,第一次运行程序出现"段错误"并没有出现core文件,一般linux操作系统默认core文件的大小都是0,需要手动设置一下。
调试core文件
core文件是个二进制文件,需要用相应的工具来分析程序崩溃时的内存映像。
linux下可以用gdb来调试core文件 。
从上面我们可以清楚的看到我们的程序是在那个地方出现了错误。
呵呵,有了这种方法,我想以后我们可以不再那么惧怕"段错误"了。
=============================GDB调试段错误===================================
我们打算使用gdb去解决为什么下面的程序(文件为segfault.c)引起了段错误的问题。下面的这段程序是从用户那里读入一行文本字串然后显示在屏幕上。然而,如下当前的程序并不会如期执行...
第一步是使用带有调试标志(debugging flags)的方式编译这段代码,如下:
~# gcc -g segfault.c
然后运行:
Hello World!
Segmentation fault
这并不是我们所期待的。是时候启动强大的gdb了。
~# gdb a.out
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.
Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
我们直接运行就来看看到底发生了什么:
Starting program: /home/dgawd/cpsc/363/a.out
test string
Program received signal SIGSEGV, Segmentation fault.
0x4007fc13 in _IO_getline_info () from /lib/libc.so.6
我们收到了来自操作系统的SIGSEGV信号。这就意味着我们试图去访问一段非法的内存,让我们试试backtrace(= bt)命令:
(gdb) backtrace
0x4007fc13 in _IO_getline_info () from /lib/libc.so.6
0x4007fb6c in _IO_getline () from /lib/libc.so.6
0x4007ef51 in fgets () from /lib/libc.so.6
0x80484b2 in main (argc=1, argv=0xbffffaf4) at segfault.c:10
0x40037f5c in __libc_start_main () from /lib/libc.so.6
这里我们只关心我们自己的代码,因此我们就切换到3号堆栈帧(stack frame3)来看看程序在哪里崩溃的:
(gdb) frame 3
0x80484b2 in main (argc=1, argv=0xbffffaf4) at segfault.c:10
fgets(buf, 1024, stdin)
哦,原来是调用fgets引起的崩溃。一般的,我们都假设库函数比如fgets都可以正确地工作(如果不是这样的话,我们的麻烦就大了)。因此这个问题的原因就一定是其中我们的一个参数的问题。你也许不知道‘stdin’是一个全局的变量,它是被stdio 库创建的。因此我们假定这个参数是正确的。那么剩下的就只能是‘buf’了,然后查看buf当前的值:
(gdb) print buf
buf的值是0x0,也就是NULL指针。这并不是我们锁期待的 —— buf应该指向第8行代码分配到的内存。因此我们需要返回到第8行并看看在哪里发生了什么。首先kill掉我们程序当前运行的调用:
(gdb) kill
Kill the program being debugged? (y or n) y
(注意:不用使用quit直接退出gdb,这样比较麻烦。直接kill掉当前的程序调用即可)
然后在第8行设置一个断点:
(gdb) break segfault.c:8
Breakpoint 1 at 0x8048486: file segfault.c, line 8.
再次运行程序:
Starting program: /home/dgawd/cpsc/363/a.out
Breakpoint 1, main (argc=1, argv=0xbffffaf4) at segfault.c:8
buf = malloc(1&&31);
我们检查malloc调用前后buf值的变化。初始化buf以前,其值应该是一个随机杂乱值(garbage),就像这里的:
(gdb) print buf
$2 = 0xbffffaa8 "鳃??\177\003@t`\001@\001"
我们step over(单步执行)malloc调用然后再次检查buf的值:
(gdb) next
fgets(buf, 1024, stdin);
(gdb) print buf
可见调用了malloc之后,buf是NULL。如果你查看malloc的手册页(man page),你就会发现malloc在不能分配够所需的内存的时候就会返回NULL。因此确定是我们的malloc失败了。让我们返回到代码再次看看:
buf = malloc(1&&31);
哦,表达式1&&31(整型1左移31次,原文错写为右移)是, 或4GB (gigabytes).很少有机器会有这样的内存——大多数只有256MB(显然这篇文章有年头了,都什么年代了,这点内存操作系统估计启动一半就挂了)。因此malloc必然会失败。此外,在fgets中我们只读入1024字节。所有的额外空间都会白白浪费掉,尽管我们可以分配到。这里我们将1&&31改为1024(或者1&&9),这样程序就会按照我们的期望运行了:
Hello World!
Hello World!
这样你就可以知道怎样使用gdb来调试段错误了,这是非常有用的。这个例子同时也说明了一个非常重要的准则:总是检查malloc的返回值!拥有美好的一天(说实在,我让段错误恶心了一天。但以后就应该不太恶心了,以后每一天都美好吧 ^_^)。
C语言再学习 -- 段错误(核心已转储)
参看:Linux下的段错误产生的原因及调试方法参看:Linux环境下段错误的产生原因及调试方法小结参看:维基百科--Segmentation fault参看:LINUX内核段错误调试详细指南精品培训P...
C语言 段错误Segmentation Fault 一种情形的简单分析
Linux环境下C语言编程遇到的最多的错误可能非“段错误”莫属了,究其原因就是访问的内存超出了系统给这个程序所设定的内存空间,例如访问了不存在的内存地址、访问了系统保护的内存地址、访问了只读的内存地址...
C语言段违例,段错误例子
void bubble(int *s,int length);
void swap(int *p,int *q);
int main(){
C语言 --段错误(核心已转储)
文章原地址:https://blog.csdn.net/qq_/article/details/ (侵删欠)一、什么是段错误?一旦一个程序发生了越界访问,cpu 就会产...
总结了C++编程过程中常出现的段错误,以及预防出现段错误的方法... 所需: 10 积分/C币 开通VIP 立即下载 评论共有0条 &em&C语言段错误&/em& 总结 段错误整理 立即下载
段错误的调试,通过4种方法来解决编程过程中出现的段错误... 上传者: maohuidong 时间:
综合评分: 4 积分/C币:3
&em&C语言段错误&/em&详解 立即下载
最近在Linux环境下做C语言项目,由于是在一个原有项目基础之上进行二次开发,而且项目工程庞大复杂,出现了不少问题,其中遇到最多、花费时间最长的问题就是著名的“段错误”(Segmentation Fa...
当写c语言时,经常遇到段错误,很多人都是用printf,但是当程序比较大时,就比较难找了,或者当程序运行时并不会立即出现段错误,而是经过很长一段时间才会出现那么用printf显然不行。这时就可以使用g...
段错误(核心已存储)问题研究
没有更多推荐了,C++调试过程中最麻烦的问题—运行时错误_C语言中文网
&&C语言辅导班&&&&
&&C++辅导班&&&&
&&算法/数据结构辅导班&&&&
读者QQ交流群:loading...
&&/&&&&/&&&&/&&
在调试过程中,运行时错误是最麻烦的问题。因为编译错误可以由编译器检查出来,而大多数编译器对运行时错误却无能为力。查错和纠错的工作完全由用户自己来完成。
运行时错误还分为两种:
一种是由于考虑不周或输入错误导致程序异常(Exception),比如数组越界访问,除数为零,堆栈溢出等等。
另一种是由于程序设计思路的错误导致程序异常或难以得到预期的效果。
对于第一类运行时错误,我们不需要重新设计解决问题的思路,认为当前算法是可行的、有效的。我们只需要找出输入的错误或考虑临界情况的处理方法即可。对于第二类运行时错误,不得不遗憾地说,一切都要从头再来。
见识运行时错误
由于编译器无法发现运行时错误,这些错误往往是在程序运行时以五花八门的形式表现出来。下面就是典型的几种因运行时错误引起的问题:
(1)WindowsXP错误报告
(2)内存不能为Read/Written
(3)非法操作
(4)Debug错误
查找错误点
语法错误的位置能很快地被编译器找到,而运行时错误的位置却很难被我们发现。即使我们一条条地检查语句,也未必能检查出什么。所以,在这里要介绍一种查找导致运行时错误的语句的方法。
我们知道,带有运行时错误的程序是可以运行的。当它运行到一个产生错误的语句时,就提示出错了。根据这个特点,我们可以用输出语句来判断程序的运行流程。下面就让我们来看一段有运行时错误的程序:(程序11.4)
#include &iostream&
int main()
& &char a[5],b[5];
& &int alen=0,blen=0;//记录字符串a和b的长度
& &cin &&a &&b;
& &for (int i=0;a[i]!='\0' && b[i]!='\0';i++)//计算字符串的长度
& & & if (a[i]!='\0')
& & & & &alen++;
& & & if (b[i]!='\0')
& & & & &blen++;
& &char *c=new char[alen+blen];//申请堆内存,存放连接后的字符串
& &for (i=0;i&=alen+i++)//把字符串a和b连接复制到字符串c
& & & if (i&alen)
& & & & &c[i]=a[i];
& & & else
& & & & &c[i]=b[i-alen];
& &cout &&c &&
& &delete []//释放堆内存
& &return 0;
运行结果:
TomatoStudio
udioTomat  葺葺葺葺癅
在程序运行结束之前,提示Debug Error,它属于一种运行时错误。而且根据输出的一些内容,发现程序也没有达到连接字符串的目的。所以我们让程序输出更多信息,查找错误原因。首先在计算字符串a和b的长度后,输出他们的长度,即在第一个for语句后添加一句cout &&&alen=& &&alen &&&blen=& &&blen &&。
运行结果:
TomatoStudio
alen=4blen=4
udioTomat  葺葺葺葺癅
OOTTMA字符串长为6,TomatoStudio字符串长为12。根据程序运行结果,我们发现计算出的字符串长度有问题。所以我们必须检查实现该功能的语句。另外,由字符串长度我们可以想到申请空间是否足够的问题。发现数组的空间只能存放5个字符,而现在两个字符串都已经超过这个限制。于是把数组空间扩大,该作char a[20],b[20];。
运行结果:
TomatoStudio
alen=6blen=6
OOTTMATomatoS  葺葺癅
发现字符串a的长度已经正确,可是字符串b的长度为什么不对呢?经过多次尝试,我们发现,正确的字符串长度总是较短的字符串。所以我们想到检查循环继续的条件是否正确,如果过早地终止循环,就会导致这种情况。果然,a[i]!='\0' && b[i]!='\0'意味着只要有一个字符串结束,那么长度计算就结束了,故把&&改成||。
运行结果:
TomatoStudio
alen=35blen=41
这么一改,居然两个长度全都错了。我们不禁要思考为什么会这样了:用一个for语句来计算两个字符串的长度,当循环变量越过任一个字符串的结尾符以后又误认为它没有结束,所以输出的长度远远长于字符串的实际长度。我们把计算字符串长度用两个for语句来实现。即程序被改写成这样:
#include &iostream&
int main()
& &char a[20],b[20];
& &cin &&a &&b;
& &for (int alen=0;a[alen]!='\0';alen++);//计算字符串a的长度
& & & for (int blen=0;b[blen]!='\0';blen++);//计算字符串b的长度
& & & & &cout &&&alen=& &&alen &&&blen=& &&blen &&
& &char *c=new char[alen+blen];
& &for (int i=0;i&=alen+i++)
& & &if (i&alen)
& & & & c[i]=a[i];
& & & else
& & & & c[i]=b[i-alen];
& &cout &&c &&
& &delete []
& &return 0;
运行结果:
TomatoStudio
alen=6blen=12
OOTTMATomatoStudio
现在两个字符串的长度都正确了,输出的内容也实现了字符串的连接,但是Debug Error仍然存在。继续检查,发现剩下的语句和申请的堆内存空间字符串c有关了。于是先检查c是否有越界访问。根据c申请的空间大小,发现for语句中循环继续的条件有错误,导致越界访问,把它改成i&alen+。
运行结果:
TomatoStudio
alen=6blen=12
OOTTMATomatoStudio  @
Debug Error已经没有了,看来造成这个错误的原因就是越界了。但是现在输出的字符串后面有乱码,可能是结尾符被忽略了。检查程序,发现alen+blen是两字符串长度,但是没有考虑结尾符,所以要给字符串c增加一个字符的空间。程序改写成如下:
#include &iostream&
int main()
& &char a[20],b[20];
& &cin &&a &&b;
& &for (int alen=0;a[alen]!='\0';alen++);
& & & for (int blen=0;b[blen]!='\0';blen++);
& & & & &//cout &&&alen=& &&alen &&&blen=& &&blen &&
& & & & &char *c=new char[alen+blen+1];
& &for (int i=0;i&alen+blen+1;i++)
& & & if (i&alen)
& & & & &c[i]=a[i];
& & & else
& & & & &c[i]=b[i-alen];
& &cout &&c &&
& &delete []
& &return 0;
运行结果:
TomatoStudio
OOTTMATomatoStudio
至此,程序修改完成。在目前的测试数据下,不再出现运行时错误,并且也能实现字符串连接的功能。
编程帮,一个分享编程知识的公众号。跟着一起学习,每天都有进步。
通俗易懂,深入浅出,一篇文章只讲一个知识点。
文章不深奥,不需要钻研,在公交、在地铁、在厕所都可以阅读,随时随地涨姿势。
文章不涉及代码,不烧脑细胞,人人都可以学习。
当你决定关注「编程帮」,你已然超越了90%的程序员!
微信扫描二维码关注
本站精品教程
loading...
验证消息:严长生C语言错误调试大全_百度文库
您的浏览器Javascript被禁用,需开启后体验完整功能,
享专业文档下载特权
&赠共享文档下载特权
&100W篇文档免费专享
&每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
C语言错误调试大全
阅读已结束,下载本文需要
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
加入VIP
还剩14页未读,
定制HR最喜欢的简历
你可能喜欢}

我要回帖

更多关于 C语言调试过程中出现的问题 的文章

更多推荐

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

点击添加站长微信