Linux下的段错误产生的原因及调试方法
了解计算机编程中的常见错误与调试方法

了解计算机编程中的常见错误与调试方法在计算机编程过程中,常常会遇到各种错误和bug,这对于开发者来说是一件非常头疼的事情。
然而,通过了解这些常见错误和相应的调试方法,我们可以更快地解决这些问题,提高编程效率。
本文将介绍一些常见的编程错误,并提供相应的调试方法。
一、语法错误语法错误是最常见的错误之一,它通常是由于不正确的代码规范或拼写错误造成的。
这种错误往往会导致编译器无法正确解析代码,从而产生编译错误。
解决语法错误的方法是仔细检查代码,查找错误的拼写、标点符号和语法规范。
可以借助编程编辑器的语法高亮和自动补全功能来减少这种错误的发生。
同时,注意在编程过程中保持良好的代码风格和规范,这有助于减少语法错误的出现。
二、逻辑错误逻辑错误是指程序在运行过程中产生错误的情况,通常是由于程序员的思维逻辑错误或代码顺序错误所导致的。
这种错误在编译过程中不会被发现,程序可以正常运行,但结果却不符合预期。
调试逻辑错误的方法是使用调试工具来逐步执行程序,观察程序的执行流程,并检查每一步的结果是否符合预期。
可以使用断点来暂停程序的执行,查看变量的值和代码执行路径,以找出逻辑错误的根源。
此外,还可以通过添加输出语句来检查程序的执行过程。
三、运行时错误运行时错误是指在程序运行过程中发生的错误,例如数组越界、空指针引用等。
这种错误通常是由于程序对于某些条件的处理不够严谨或者与外部环境的交互导致的。
解决运行时错误的方法是在编程过程中加入异常处理机制。
通过捕获异常并给出相应的处理方式,可以使程序在发生错误时能够优雅地退出或者继续执行。
此外,还可以使用断言等方法来预防运行时错误的发生,提高程序的健壮性。
四、算法错误算法错误指的是程序设计中的逻辑错误,造成程序逻辑的不合理或者效率低下。
这种错误通常是由于对问题理解不准确、算法设计不恰当等原因造成的。
调试算法错误的方法是通过思考和分析来找出问题所在,并重新设计相应的算法。
可以借助数据结构与算法的知识,从程序的输入、输出和过程中寻找问题的源头。
内存调试工具 valgrind

内存调试工具valgrind来源::linux下面用c++写代码,在所难免会遇到segmentation fault(段错误)。
个人在编写ns扩展模块时候,遇到过很多段错误,虽然运行时刻经常由程序抛出段错误,但是段错误的发生的程序级别的原因多种多样,不过归结到系统级别上,段错误都是由于内存原因引起的(个人总结)。
会造成内存错误的程序级别的原因,也就是我们程序员所经常犯的错误大致可以分为以下几个方面:1,使用未初始化的指针-这是必然的,指针指空的东西,必然出错。
2,重复删除一个指针-必然,再次删除就会删除一个已经分配给别的程序的数据或者其他。
3,内存冲突-由于程序声明的两块数据区域重叠,造成混乱。
4,混杂的指针错误-只能具体问题具体分析,情况比较复杂。
对于一位刚开始用c++在linux编程的人来说,最常遇到的应该的就是1与2了。
当工程规模比较大,程序由小组完成而后整合等的情况下,很容易出现2,3,4的情况。
这时候的调试比较麻烦,也需要很多耐心。
我在做的wimax mesh的项目就是这样。
对于一个timer的使用,没有初始化,造成的段错误,一目了然。
工程进展非常顺利。
当工程做到50%时候(11.08号),遇到了一个段错误,结果调试到12.02号才调出来!我就来说一下我的调试历程吧!真是一波三折阿!开始的时候以为是1或者2的情况,反复检查,不是这样。
然后怀疑3或者4,结果由于没有使用任何工具,只是在代码中加打印信息,这时候只能把错误定位到transmit(p)这个函数上。
但是这个函数我只写了一行,就是transmit(p){downtarget_-recv(p,(Handle*)NULL);}程序在这个地方出错实在让人摸不到头绪,因为再往下执行就不是我代码的问题了,而是下层已有代码甚至是系统代码的问题阿!非常困扰!然后开始用gdb调试,gdb是一个很好的很强大的调试工具,我用的命令行的,所能完成的功能和vc下的调试工具差不多,只是需要看什么变量就是要用print×来看罢了,不过功能决不比它差。
编程中的错误调试和排查方法

编程中的错误调试和排查方法在软件开发和编程过程中,错误是一种常见且不可避免的情况。
无论是小规模项目还是大型系统,都可能出现各种各样的错误。
因此,了解正确的错误调试和排查方法对于程序员来说至关重要。
本文将介绍几种常用的调试和排查方法。
一、运行时错误运行时错误是指在程序运行期间发生的错误。
常见的运行时错误包括空指针引用、数组越界、类型转换错误等。
对于此类错误,通常可以采用以下方法进行调试和排查:1. 打印调试信息:在代码中插入打印语句,输出相关的变量和状态信息,以便定位错误发生的位置。
2. 使用调试工具:现代的集成开发环境(IDE)通常提供了强大的调试工具,如断点调试、变量查看、堆栈跟踪等。
通过使用这些工具,可以逐行跟踪代码执行过程,查看变量的值,从而找到错误的原因。
3. 写单元测试:编写单元测试是一种常用的调试和排查方法。
通过编写针对特定函数或模块的测试用例,可以快速定位和修复代码中的错误。
二、逻辑错误逻辑错误是指程序的逻辑设计有误导致程序不能按照预期的方式工作。
例如,程序输出的结果与预期结果不符合。
对于逻辑错误,可以采取以下方法进行调试和排查:1. 代码审查:请同事或其他开发者对你的代码进行审查,以查找潜在的逻辑错误。
他们可以提供新的视角,发现你可能忽略的问题。
2. 使用断言:在关键的代码部分插入断言语句,检查某个条件是否为真。
如果条件不满足,程序会抛出异常,从而帮助你找到问题所在。
3. 跟踪执行路径:通过观察程序执行的路径,找出可能导致逻辑错误的分支和条件语句。
可以使用调试工具来跟踪程序的执行路径,或者使用日志记录来定位问题。
三、性能问题性能问题是指程序在运行时出现的延迟、卡顿或资源消耗过高等情况。
对于性能问题,可以采用以下方法进行调试和排查:1. 性能测试:使用性能测试工具对程序进行测试,以测量程序的性能指标。
通过对比测试结果,找出性能瓶颈所在。
2. 代码优化:对于发现的性能瓶颈,可以对相应的代码进行优化。
在linux下利用程序崩溃后的core文件分析bug(转载)

当我们的程序崩溃时,内核有可能把该程序当前内存映射到core文件里,方便程序员找到程序出现问题的地方。
最常出现的,几乎所有C程序员都出现过的错误就是“段错误”了。
也是最难查出问题原因的一个错误。
下面我们就针对“段错误”来分析core文件的产生、以及我们如何利用core文件找到出现崩溃的地方。
何谓core文件当一个程序崩溃时,在进程当前工作目录的core文件中复制了该进程的存储图像。
core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的。
当程序接收到以下UNIX信号会产生core文件:在系统默认动作列,“终止w/core”表示在进程当前工作目录的core文件中复制了该进程的存储图像(该文件名为core,由此可以看出这种功能很久之前就是UNIX功能的一部分)。
大多数UNIX 调试程序都使用core文件以检查进程在终止时的状态。
core文件的产生不是POSIX.1所属部分,而是很多UNIX版本的实现特征。
UNIX第6版没有检查条件(a)和(b),并且其源代码中包含如下说明:“如果你正在找寻保护信号,那么当设置-用户-ID命令执行时,将可能产生大量的这种信号”。
4.3 + BSD产生名为core.prog的文件,其中prog是被执行的程序名的前1 6个字符。
它对core文件给予了某种标识,所以是一种改进特征。
表中“硬件故障”对应于实现定义的硬件故障。
这些名字中有很多取自UNIX早先在DP-11上的实现。
请查看你所使用的系统的手册,以确切地确定这些信号对应于哪些错误类型。
下面比较详细地说明这些信号。
? SIGABRT 调用abort函数时产生此信号。
进程异常终止。
? SIGBUS 指示一个实现定义的硬件故障。
? SIGEMT 指示一个实现定义的硬件故障。
EMT这一名字来自PDP-11的emulator trap 指令。
? SIGFPE 此信号表示一个算术运算异常,例如除以0,浮点溢出等。
? SIGILL 此信号指示进程已执行一条非法硬件指令。
段错误

C语言中的段错误编译完程序,执行的时候,有时会莫名的出现“Segment fault”,即段错误,段错误是让许多C程序员都头疼的提示,因为对于这种模糊的提示,很难判断错误在哪里。
那么什么事段错误呢?以及怎么发现程序中的段错误以及如何避免发生段错误呢?1.什么是段错误?所谓的段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。
一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation fault就出现了。
通过上面的解释,段错误应该就是访问了不可访问的内存,这个内存区要么是不存在的,要么是受到系统保护的。
2.那什么操作会引起段错误呢?粗略的分一下类:1)往受到系统保护的内存地址写数据有些内存是内核占用的或者是其他程序正在使用,为了保证系统正常工作,所以会受到系统的保护,而不能任意访问。
2)内存越界(数组越界,变量类型不一致等)3)其他例如:<1>定义了指针后记得初始化,在使用的时候记得判断是否为NULL<2>在使用数组的时候是否被初始化,数组下标是否越界,数组元素是否存在等<3>在变量处理的时候变量的格式控制是否合理等3.那么我们如何去发现程序中的段错误呢?通过学习前人的经验和开发的工具,不断的尝试和研究,找出更恰当的方法来避免、发现并处理它。
对于一些常见的地方,我们可以避免,对于一些“隐藏”的地方,我们要发现它,发现以后就要及时处理,避免留下隐患。
用gdb来调试,在运行到段错误的地方,会自动停下来并显示出错的行和行号,gdb也是最常用的,如果需要用gdb调试,记得在编译的时候加上-g参数。
Segmentationfault(coredumped)错误的一种解决场景

Segmentationfault(coredumped)错误的⼀种解决场景错误类型Segmentation fault (core dumped)产⽣原因Segmentation fault 段错误。
Core Dump 核⼼转储(是操作系统在进程收到某些信号⽽终⽌运⾏时,将此时进程地址空间的内容以及有关进程状态的其他信息写出的⼀个磁盘⽂件。
这种信息往往⽤于调试),其实“吐核”这个词形容的很恰当,就是核⼼内存吐出来。
出现这种错误可能的原因(其实就是访问了内存中不应该访问的东西):1,内存访问越界:(1)数组访问越界,因为下标出超出了范围。
(2)搜索字符串的时候,通过字符串的结尾符号来判断结束,但是实际上没有这个结束符。
(3)使⽤strcpy, strcat, sprintf, strcmp,strcasecmp等字符串操作函数,超出了字符中定义的可以存储的最⼤范围。
使⽤strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函数防⽌读写越界。
2,多线程程序使⽤了线程不安全的函数。
3,多线程读写的数据未加锁保护。
对于会被多个线程同时访问的全局数据,应该注意加锁保护,否则很容易造成核⼼转储4,⾮法指针(1)使⽤NULL指针(2)随意使⽤指针类型强制转换,因为在这种强制转换其实是很不安全的,因为在你不确认这个类型就应该是你转化的类型的时候,这样很容易出错,因为就会按照你强制转换的类型进⾏访问,这样就有可能访问到不应该访问的内存。
5,堆栈溢出不要使⽤⼤的局部变量(因为局部变量都分配在栈上),这样容易造成堆栈溢出,破坏系统的栈和堆结构,导致出现莫名其妙的错误。
解决场景在linux的虚拟机上跑了⼀个数据结构,在虚拟机上出现上述错误,在Windows的宿主机弹出错误。
于是试运⾏⼀个相似的较简单的哈希函数,虚拟机上出现相同错误,,注意到以下代码:// generates a hash value for a sting// same as djb2 hash functionunsigned int CountMinSketch::hashstr(const char *str) {unsigned long hash = 5381;int c;while (c = *str++) {hash = ((hash << 5) + hash) + c; /* hash * 33 + c */}return hash;}这是⼀个针对字符串的哈希函数,其中⼀⾏hash = ((hash << 5) + hash) + c; /* hash * 33 + c */是问题所在,针对较长的字符串,这个hash变量会不断变⼤,甚⾄溢出。
编程中常见的错误类型和调试技巧
编程中常见的错误类型和调试技巧在编程过程中,常见的错误类型包括语法错误、逻辑错误和运行时错误。
下面我们将分别介绍这三种错误类型以及对应的调试技巧。
1.语法错误语法错误是程序中最常见的错误类型之一。
它通常是由于代码中缺少分号、括号不匹配、拼写错误等引起的。
当代码存在语法错误时,程序将无法编译或者运行时会报错。
调试技巧:-使用IDE编辑器:IDE编辑器通常会对语法错误进行标记和提示,帮助开发者及时发现问题并进行修正。
-逐行排查:逐行阅读代码,检查每个字符是否符合语法规范。
-利用编译器报错信息:编译器会给出具体的错误信息和位置,开发者可以根据提示进行修正。
2.逻辑错误逻辑错误是指代码逻辑上的错误,导致程序的运行结果与预期不符。
这类错误通常不会导致程序崩溃,但会导致程序执行结果不正确。
调试技巧:-使用调试工具:调试工具可以帮助开发者对程序进行逐行调试,查看变量的取值情况、函数的执行流程,帮助发现逻辑错误。
-打印调试信息:在关键位置添加打印语句,输出变量的取值和程序执行流程,有助于排查逻辑错误。
-编写单元测试:编写单元测试可以帮助开发者快速定位逻辑错误,保证程序的功能正确性。
3.运行时错误运行时错误是指程序在运行过程中出现的错误,导致程序崩溃或者报错。
常见的运行时错误包括空指针异常、数组越界、内存泄漏等。
调试技巧:-异常处理:在代码中使用异常处理机制,捕获并处理可能出现的异常,避免程序崩溃。
-使用断点调试:在关键位置设置断点,可以观察程序在该位置的执行情况,有助于发现运行时错误。
-内存检测工具:使用内存检测工具检测程序的内存使用情况,及时发现并解决内存泄漏等问题。
除了上述常见的错误类型和调试技巧,还有一些编程中常见的调试技巧如下:-修改少量代码:当发现问题时,先尝试修改少量代码,逐步缩小问题范围,有助于更快地定位错误。
-查找文档:查阅相关文档、资料、论坛等,寻找对应的解决方案和经验分享。
-请教他人:与同行交流、请教更有经验的开发者,获取他们的建议和帮助。
linux崩溃有效排查方法
linux崩溃有效排查方法1. 查看系统日志:系统日志记录了系统的活动和错误信息。
你可以查看 `/var/log` 目录下的日志文件,如 `/var/log/syslog`、`/var/log/messages` 等,以获取关于崩溃的线索。
2. 使用 dmesg 命令:dmesg 命令用于显示内核环形缓冲区的消息。
它可以提供有关系统启动时的信息以及内核检测到的错误消息。
执行 `dmesg` 命令可以查看系统崩溃前的最后一些消息。
3. 分析崩溃转储文件:如果系统崩溃导致生成了崩溃转储文件(例如,`/var/crash/` 目录下的文件),你可以使用相关工具来分析这些文件,以确定崩溃的原因。
常用的工具包括 `gdb`、`mdb` 等。
4. 检查硬件问题:硬件故障也可能导致系统崩溃。
你可以检查硬件设备,如内存、硬盘、电源等是否正常工作。
可以使用硬件检测工具来进行诊断。
5. 查看进程状态:使用如 `top`、`ps` 等命令来查看系统当前的进程状态。
如果有异常的进程占用了大量资源或导致系统不稳定,可能是崩溃的原因之一。
6. 检查内核模块:某些内核模块的问题也可能导致系统崩溃。
你可以使用 `lsmod` 命令查看加载的内核模块,并检查是否有异常的模块。
7. 进行系统更新:确保你的 Linux 系统以及相关的软件包都是最新的版本。
有时更新可以修复已知的漏洞和问题。
8. 寻求专家帮助:如果你无法确定崩溃的原因或无法解决问题,可以寻求 Linux 专家或相关技术支持人员的帮助。
需要根据具体情况选择适当的排查方法。
在排查过程中,记录你所采取的步骤和结果,这有助于更快速地定位和解决问题。
Linux下core文件调试方法
Linux下core⽂件调试⽅法在程序不寻常退出时,内核会在当前⼯作⽬录下⽣成⼀个core⽂件(是⼀个内存映像,同时加上调试信息)。
使⽤gdb来查看core⽂件,可以指⽰出导致程序出错的代码所在⽂件和⾏数。
1.core⽂件的⽣成开关和⼤⼩限制(1)使⽤ulimit -c命令可查看core⽂件的⽣成开关。
若结果为0,则表⽰关闭了此功能,不会⽣成core⽂件。
通过上⾯的命令修改后,⼀般都只是对当前会话起作⽤,当你下次重新登录后,还是要重新输⼊上⾯的命令,所以很⿇烦。
我们可以把通过修改 /etc/profile⽂件来使系统每次⾃动打开。
步骤如下:1.⾸先打开/etc/profile⽂件⼀般都可以在⽂件中找到这句语句:ulimit -S -c 0 > /dev/null 2>&1.ok,根据上⾯的例⼦,我们只要把那个0 改为 unlimited 就ok了。
然后保存退出。
2.通过source /etc/profile 使当期设置⽣效。
3.通过ulimit -c 查看下是否已经打开。
其实不光这个命令可以加⼊到/etc/profile⽂件中,⼀些其他我们需要每次登录都⽣效的都可以加⼊到此⽂件中,因为登录时linux都会加载此⽂件。
⽐如⼀些环境变量的设置。
还有⼀种⽅法可以通过修改/etc/security/limits.conf⽂件来设置,⾸先以root权限登陆,然后打开/etc/security/limits.conf⽂件,进⾏配置:#vim /etc/security/limits.conf<domain> <type> <item> <value>* soft core unlimited(2)使⽤ulimit -c filesize命令,可以限制core⽂件的⼤⼩(filesize的单位为kbyte)。
若ulimit -c unlimited,则表⽰core⽂件的⼤⼩不受限制。
csegmentfault的常见原因
csegmentfault的常见原因Segmentation fault(段错误)是一种在编程中常见的错误类型,通常发生于访问无效的内存区域时。
下面将介绍一些导致段错误的常见原因:1.访问NULL指针:当一个指针被赋值为NULL,或者没有被正确初始化时,尝试通过该指针访问内存区域时会导致段错误。
2.数组越界:当访问数组超出其索引范围时,会导致段错误。
这可能发生在访问数组时使用不正确的索引或者未正确初始化的指针。
3.使用未分配的内存:如果尝试使用未分配的内存,例如使用malloc或new动态分配内存之后,没有正确释放或分配不正确的大小,可能导致段错误。
4.指针操作错误:当对指针进行错误的操作时,会导致段错误。
例如,使用无效的指针进行解引用、在无效的指针上调用函数。
5.栈溢出:当递归调用栈过深或者局部变量占用空间过多时,栈可能会溢出,导致段错误。
6.移动非法的内存块:当试图移动已经释放或非法的内存块时,如使用memcpy函数时,可能会导致段错误。
7.误使用指针:在多线程环境中,如果同时访问同一个指针而没有进行同步操作,可能会导致段错误。
8.非法的指令:当程序中的指令不符合CPU的要求,例如访问特殊寄存器或执行非法指令,可能会导致段错误。
以上只是一些导致段错误的常见原因,具体情况可能因项目的不同而有所不同。
为了避免段错误的发生,以下是一些常见的防范措施:1.确保指针被正确初始化,并且为NULL时不进行解引用操作。
2.在使用指针前对其进行有效性检查,确保其指向有效的内存区域。
3.在使用动态分配的内存后,及时释放内存,并确保分配和释放的大小匹配。
4.避免数组越界访问,并确保使用正确的索引。
5.尽量避免过深的递归调用,或者使用迭代替代递归。
6.谨慎使用指针操作,确保对指针进行正确的解引用和操作。
7.在多线程环境中,使用同步机制(如互斥锁)来避免指针的误用。
8.避免使用无效的指令,确保指令集与CPU要求一致。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
而言之,产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址.
一般来说,段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation fault就出现了.
在编程中以下几类做法容易导致段错误,基本是是错误地使用指针引起的 1)访问系统数据区,尤其是往 系统保护的内存地址写数据 最常见就是给一个指针以0地址 2)内存越界(数组越界,变量类型不一致等) 访问到不属于你的内存区域
解决方法 我们在用C/C++语言写程序的时侯,内存管理的绝大部分工作都是需要我们来做的。实际上,内存管理是一个比较繁琐的工作,无论你多高明,经验多丰富,难 免会在此处犯些小错误,而通常这些错误又是那么的浅显而易于消除。但是手工“除虫”(debug),往往是效率低下且让人厌烦的,本文将就"段错误"这个 内存访问越界的错误谈谈如何快速定位这些"段错误"的语句。 下面将就以下的一个存在段错误的程序介绍几种调试方法: 1 dummy_function (void) 2 { 3 unsigned char *ptr = 0x00; 4 *ptr = 0x00; 5 } 6 7 int main (void) 8 { 9 dummy_function (); 10 11 return 0; 12 }
作为一个熟练的C/C++程序员,以上代码的bug应该是很清楚的,因为它尝试操作地址为0的内存区域,而这个内存区域通常是不可访问的禁区,当然就会出错了。我们尝试编译运行它: xiaosuo@gentux test $ ./a.out 段错误 果然不出所料,它出错并退出了。 1.利用gdb逐步查找段错误: 这种方法也是被大众所熟知并广泛采用的方法,首先我们需要一个带有调试信息的可执行程序,所以我们加上“-g -rdynamic"的参数进行编译,然后用gdb调试运行这个新编译的程序,具体步骤如下: xiaosuo@gentux test $ gcc -g -rdynamic d.c xiaosuo@gentux test $ gdb ./a.out GNU gdb 6.5 Copyright (C) 2006 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"...Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) r Starting program: /home/xiaosuo/test/a.out
Program received signal SIGSEGV, Segmentation fault. 0x08048524 in dummy_function () at d.c:4 4 *ptr = 0x00; (gdb)
哦?!好像不用一步步调试我们就找到了出错位置d.c文件的第4行,其实就是如此的简单。 从这里我们还发现进程是由于收到了SIGSEGV信号而结束的。通过进一步的查阅文档(man 7 signal),我们知道SIGSEGV默认handler的动作是打印”段错误"的出错信息,并产生Core文件,由此我们又产生了方法二。 2.分析Core文件: Core文件是什么呢?
The default action of certain signals is to cause a process to terminate and produce a core dump file, a disk file containing an image of the process's memory at the time of termination. A list of the signals which cause a process to dump core can be found in signal(7).
以 上资料摘自man page(man 5 core)。不过奇怪了,我的系统上并没有找到core文件。后来,忆起为了渐少系统上的拉圾文件的数量(本人有些洁癖,这也是我喜欢Gentoo的原因 之一),禁止了core文件的生成,查看了以下果真如此,将系统的core文件的大小限制在512K大小,再试: xiaosuo@gentux test $ ulimit -c 0 xiaosuo@gentux test $ ulimit -c 1000 xiaosuo@gentux test $ ulimit -c 1000 xiaosuo@gentux test $ ./a.out 段错误 (core dumped) xiaosuo@gentux test $ ls a.out core d.c f.c g.c pango.c test_iconv.c test_regex.c
core文件终于产生了,用gdb调试一下看看吧: xiaosuo@gentux test $ gdb ./a.out core GNU gdb 6.5 Copyright (C) 2006 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"...Using host libthread_db library "/lib/libthread_db.so.1".
warning: Can't read pathname for load map: 输入/输出错误. Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 Core was generated by `./a.out'. Program terminated with signal 11, Segmentation fault. #0 0x08048524 in dummy_function () at d.c:4 4 *ptr = 0x00;
哇,好历害,还是一步就定位到了错误所在地,佩服一下Linux/Unix系统的此类设计。 接着考虑下去,以前用windows系统下的ie的时侯,有时打开某些网页,会出现“运行时错误”,这个时侯如果恰好你的机器上又装有windows的编译器的话,他会弹出来一个对话框,问你是否进行调试,如果你选择是,编译器将被打开,并进入调试状态,开始调试。 Linux下如何做到这些呢?我的大脑飞速地旋转着,有了,让它在SIGSEGV的handler中调用gdb,于是第三个方法又诞生了: 3.段错误时启动调试:
#include #include #include #include
void dump(int signo) { char buf[1024]; char cmd[1024]; FILE *fh;
snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid()); if(!(fh = fopen(buf, "r"))) exit(0);