Linux下的段错误(Segmentationfault)产生的原因及调试方法_第1页
Linux下的段错误(Segmentationfault)产生的原因及调试方法_第2页
Linux下的段错误(Segmentationfault)产生的原因及调试方法_第3页
Linux下的段错误(Segmentationfault)产生的原因及调试方法_第4页
Linux下的段错误(Segmentationfault)产生的原因及调试方法_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Linux下的段错误(Segmentationfault)产生的原因及调试方法(经典)2009-04-0511:25简而言之,产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址.一般来说,段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限

2、和页面交换还有程序运行级别还有内存粒度等等的信息。一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentationfault就出现了.在编程中以下几类做法容易导致段错误,基本是是错误地使用指针引起的访问系统数据区,尤其是往系统保护的内存地址写数据最常见就是给一个指针以0地址内存越界(数组越界,变量类型不一致等)访问到不属于你的内存区域解决方法我们在用C/C+语言写程序的时侯,内存管理的绝大部分工作都是需要我们来做的。实际上,内存管理是一个比较繁琐的工作,无论你多高明,经验多丰富,难免会在此处犯些小错误,而通常这些错误又是那么的浅显而易于消除。但是手工“除虫”(debug)

3、,往往是效率低下且让人厌烦的,本文将就段错误这个内存访问越界的错误谈谈如何快速定位这些段错误的语句。下面将就以下的一个存在段错误的程序介绍几种调试方法:dummy_function(void)TOC o 1-5 h zunsignedchar*ptr=0 x00;*ptr=0 x00;6intmain(void)dummy_function();10return0;作为一个熟练的C/C+程序员,以上代码的bug应该是很清楚的,因为它尝试操作地址为0的内存区域,而这个内存区域通常是不可访问的禁区,当然就会出错了。我们尝试编译运行它:xiaosuogentuxtest$./a.out段错误果然不出

4、所料,它出错并退出了。1.利用gdb逐步查找段错误:这种方法也是被大众所熟知并广泛采用的方法,首先我们需要一个带有调试信息的可执行程序,所以我们加上“-g-rdynamic的参数进行编译,然后用gdb调试运行这个新编译的程序,具体步骤如下:xiaosuogentuxtest$gcc-g-rdynamicd.cxiaosuogentuxtest$gdb./a.outGNUgdb6.5Copyright(C)2006FreeSoftwareFoundation,Inc.GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andyouarewe

5、lcometochangeitand/ordistributecopiesofitundercertainconditions.Typeshowcopyingtoseetheconditions.ThereisabsolutelynowarrantyforGDB.Typeshowwarrantyfordetails.ThisGDBwasconfiguredasi686-pc-linux-gnu.Usinghostlibthread_dblibrary/lib/libthread_db.so.1.(gdb)rStartingprogram:/home/xiaosuo/test/a.outProg

6、ramreceivedsignalSIGSEGV,Segmentationfault.0 x08048524indummy_function()atd.c:44*ptr=0 x00;(gdb)哦?!好像不用一步步调试我们就找到了出错位置d.c文件的第4行,其实就是如此的简单。从这里我们还发现进程是由于收到了SIGSEGV信号而结束的。通过进一步的查阅文档(man7signal),我们知道SIGSEGV默认handler的动作是打印”段错误的出错信息,并产生Core文件,由此我们又产生了方法二。2.分析Core文件:Core文件是什么呢?Thedefaultactionofcertainsign

7、alsistocauseaprocesstoterminateandproduceacoredumpfile,adiskfilecontaininganimageoftheprocesssmemoryatthetimeoftermination.Alistofthesignalswhichcauseaprocesstodumpcorecanbefoundinsignal(7).以上资料摘自manpage(man5core)。不过奇怪了,我的系统上并没有找到core文件。后来,忆起为了渐少系统上的拉圾文件的数量(本人有些洁癖,这也是我喜欢Gentoo的原因之一),禁止了core文件的生成,查看了

8、以下果真如此,将系统的core文件的大小限制在512K大小,再试:xiaosuogentuxtest$ulimit-c0 xiaosuogentuxtest$ulimit-c1000 xiaosuogentuxtest$ulimit-c1000 xiaosuogentuxtest$./a.out段错误(coredumped)xiaosuogentuxtest$lsa.outcored.cf.cg.cpango.ctest_iconv.ctest_regex.ccore文件终于产生了,用gdb调试一下看看吧:xiaosuogentuxtest$gdb./a.outcoreGNUgdb6.5Cop

9、yright(C)2006FreeSoftwareFoundation,Inc.GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andyouarewelcometochangeitand/ordistributecopiesofitundercertainconditions.Typeshowcopyingtoseetheconditions.ThereisabsolutelynowarrantyforGDB.Typeshowwarrantyfordetails.ThisGDBwasconfiguredasi686-pc-linux-

10、gnu.Usinghostlibthread_dblibrary/lib/libthread_db.so.1.warning:Cantreadpathnameforloadmap:输入/输出错误.Readingsymbolsfrom/lib/libc.so.6.done.Loadedsymbolsfor/lib/libc.so.6Readingsymbolsfrom/lib/ld-linux.so.2.done.Loadedsymbolsfor/lib/ld-linux.so.2Corewasgeneratedby./a.out.Programterminatedwithsignal11,Se

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

12、.段错误时启动调试:#include#include#include#includevoiddump(intsigno)charbuf1024;charcmd1024;FILE*fh;snprintf(buf,sizeof(buf),/proc/%d/cmdline,getpid();if(!(fh=fopen(buf,r)exit(0);if(!fgets(buf,sizeof(buf),fh)exit(0);fclose(fh);if(bufstrlen(buf)-1=n)bufstrlen(buf)-1=0;snprintf(cmd,sizeof(cmd),gdb%s%d,buf,get

13、pid();system(cmd);exit(0);voiddummy_function(void)unsignedchar*ptr=0 x00;*ptr=0 x00;intmain(void)signal(SIGSEGV,&dump);dummy_function();return0;编译运行效果如下:xiaosuogentuxtest$gcc-g-rdynamicf.cxiaosuogentuxtest$./a.outGNUgdb6.5Copyright(C)2006FreeSoftwareFoundation,Inc.GDBisfreesoftware,coveredbytheGNUGe

14、neralPublicLicense,andyouarewelcometochangeitand/ordistributecopiesofitundercertainconditions.Typeshowcopyingtoseetheconditions.ThereisabsolutelynowarrantyforGDB.Typeshowwarrantyfordetails.ThisGDBwasconfiguredasi686-pc-linux-gnu.Usinghostlibthread_dblibrary/lib/libthread_db.so.1.Attachingtoprogram:/

15、home/xiaosuo/test/a.out,process9563Readingsymbolsfrom/lib/libc.so.6.done.Loadedsymbolsfor/lib/libc.so.6Readingsymbolsfrom/lib/ld-linux.so.2.done.Loadedsymbolsfor/lib/ld-linux.so.20 xffffe410in_kernel_vsyscall()(gdb)bt#00 xffffe410in_kernel_vsyscall()#10 xb7ee4b53inwaitpid()from/lib/libc.so.6#20 xb7e

16、925c9instrtold_l()from/lib/libc.so.6#30 x08048830indump(signo=11)atf.c:22#4#50 x0804884cindummy_function()atf.c:31#60 x08048886inmain()atf.c:38怎么样?是不是依旧很酷?以上方法都是在系统上有gdb的前提下进行的,如果没有呢?其实glibc为我们提供了此类能够dump栈内容的函数簇,详见/usr/include/execinfo.h(这些函数都没有提供manpage,难怪我们找不到),另外你也可以通过gnu的手册进行学习。4.利用backtrace和obj

17、dump进行分析:重写的代码如下:#include#include#include#include/*Adummyfunctiontomakethebacktracemoreinteresting.*/voiddummy_function(void)unsignedchar*ptr=0 x00;*ptr=0 x00;voiddump(intsigno)void*array10;size_tsize;char*strings;size_ti;size=backtrace(array,10);strings=backtrace_symbols(array,size);printf(Obtained

18、%zdstackframes.n,size);for(i=0;isize;i+)printf(%sn,stringsi);free(strings);exit(0);intmain(void)signal(SIGSEGV,&dump);dummy_function();return0;编译运行结果如下:xiaosuogentuxtest$gcc-g-rdynamicg.cxiaosuogentuxtest$./a.outObtained5stackframes./a.out(dump+0 x19)0 x80486c20 xffffe420./a.out(main+0 x35)0 x804876f/lib/libc.so.6(_libc_start_main+0 xe6)0 xb7e02866./a.out0 x8048601这次你可能有些失望,似乎没能给出足够的信息来标示错误,不急,先看看能分析出来什么吧,用objdump反汇编程

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论