转自:http://blog.csdn.net/ab198604/article/details/6164517

版权声明:本文为博主原创文章,未经博主允许不得转载。

        在实际开发过程中,大家可能会遇到段错误的问题,虽然是个老问题,但是其带来的隐患是极大的,只要出现一次,程序立即崩溃中止。如果程序运行在PC中,segment fault的调试相对比较方便,因为可以通过串口、显示器可以查看消息,只要程序运行,通过GDB调试工具即可捕捉产生segment fault的具体原因。但是不知大家有没有想法,当程序运行在嵌入式设备上时,你所面临资源的缺乏,你没有串口打印信息,没有显示器可查看,你不知道程序运行的状态,如果程序的产生segment falut这种bug发生的周期1年之内只发生过三四次,时间又不确定,你又如何调试知道程序发生错误的具体位置呢?等等问题实在令人纠结。

        解决此问题的方式方法有如下几种:

        在产品发布之前,尽量将所有segment fault产生原因找出,全部消除(最理想情况下)

        在程序中的关键位置增加打印信息,设定打印级别,通过打信的信息缩小查bug的范围,如果是嵌入式设备,需要将这些信息写入文件,保存在flash中。

        利用看门狗喂狗,如果程序中止或长期陷入死循环,将重新加载程序

        利用Linux信号机制来解决段错误问题(有点类似于软看门狗)

       下面我着重讲解第4要点的解决方式:

        首先,我先叙述下我的总体思路,假设我的程序在某处调用一函数dummy_func(),这个函数有个segment fault段错误,如果你程序没对其进行处理,不用怀疑,你的程序马上挂掉,如果是嵌入式设备里的程序,你可能不知道产生segment fault的具体原因和具体位置,只能看log日志慢慢分析。我们知道,在linux的信号机制中,当产生segment fault错误时,程序会产生SIGSEGV信号,于是我们试想,如果我们在程序中能够及时捕捉到此信号,然后在此信号处理函数中重新加载此应用程序,就可以实现类似看门狗的功能,暂且将这种方法称之为软件看门狗吧。但是此方法只是权宜之计,它可以让你的产品在客户面前保持良好印象(因为如果程序挂掉后又重新加载了,而客户不知道),而不至于长期很频繁的去现场解决此问题,这种方式适用于产生段错误的周期具有不确定性,其实我们都知道遇到segment fault我们还得解决此问题产生的具体原因,这才是正确的解决方式。

        下面我列出完整的程序源码,虽然简单,但是非常有用:

/******************************程序开始 **********************************/

#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h> char main_status = ; /***********************
* 此函数产生一个段错误
* *********************/
void dummy_func(void)
{
printf("hello world/n");
char *p = NULL; //0地址
*p = 0x1a; //对0地址写入数据,出现段错误
return;
} /************************
* 此函数用于重新加载程序
************************/
void deal(void)
{
char buffer[];
memset(buffer, , sizeof(buffer));
sprintf(buffer, "cd ~/test");
system(buffer); /*
*此延时很重要,如果不加延时,ctrl+c的信号无法及时处理(即ctrl+c失效),程序将循环加载
* 如果不加延时,程序又重新执行后面./test1语句将重新加载应用程序了
*/
sleep(); memset(buffer, , sizeof(buffer));
sprintf(buffer, "./test1");
system(buffer);
printf ("xxxxxxxxxxxxxxx/n"); if( == main_status )
exit();
} /**************************
* 捕捉到ctrl+c信号的处理函数
**************************/
void ctrl_c_func(int signo)
{
printf("stop the demo/n");
main_status = ; //置标志位
exit();
} int ctrl_c_func_init(void)
{
int ret = ;
struct sigaction act; act.sa_handler = ctrl_c_func;
sigemptyset(&act.sa_mask);
act.sa_flags = ; ret = sigaction(SIGINT, &act, NULL);
} /****************************
* main主程序
****************************/
int main(int argc, char **argv)
{
signal(SIGSEGV, &deal); //捕捉SIGSEGV信号
signal(SIGINT, &ctrl_c_func); //捕捉SIGINT信号
// ctrl_c_func_init(); //如果不用上面捕捉,调用这个函数也行 while()
{
if( == main_status ) //如果接收到标志位,则退出
{
exit();
}
dummy_func(); //调用产生segment fault函数
}
return ;
}
/******************************程序结束 **********************************/

利用linux信号机制调试段错误(Segment fault)【转】的更多相关文章

  1. 利用linux信号机制调试段错误(Segment fault)

    在实际开发过程中,大家可能会遇到段错误的问题,虽然是个老问题,但是其带来的隐患是极大的,只要出现一次,程序立即崩溃中止.如果程序运行在PC中,segment fault的调试相对比较方便,因为可以通过 ...

  2. 【Z】段错误Segment Fault定位,即core dump文件与gdb定位

    使用C++开发系统有时会出现段错误,即Segment Fault.此类错误程序直接崩溃,通常没有任何有用信息输出,很难定位bug,因而无从解决问题.今天我们介绍core dump文件,并使用gdb进行 ...

  3. 在Linux中调试段错误(core dumped)

    在Linux中调试段错误(core dumped) 在作比赛的时候经常遇到段错误, 但是一般都采用的是printf打印信息这种笨方法,而且定位bug比较慢,今天尝试利用gdb工具调试段错误. 段错误( ...

  4. Linux下调试段错误 (gdb,core,ulimit)

    Linux环境下经常遇到某个进程挂掉而找不到原因,我们可以通过生成core file文件加上gdb来定位. (1)首先 在makefile中要增加编译调试选项 -g,才可以利用下面的gdb来调试 gc ...

  5. linux驱动调试--段错误之oops信息分析

    linux驱动调试--段错误之oops信息分析 http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29401328&id= ...

  6. linux ulimit的使用,如何产生core文件,调试段错误

    ---恢复内容开始--- 下面先简单介绍下ulimit命令: 1. limit -a 可以查看系统各种资源的限制,如: core文件大小,数据段的大小等. $ ulimit -a core file ...

  7. Linux下的段错误(Segmentation fault)

    Linux开发中常见段错误问题原因分析 1 使用非法的内存地址(指针),包括使用未经初始化及已经释放的指针.不存在的地址.受系统保护的地址,只读的地址等,这一类也是最常见和最好解决的段错误问题,使用G ...

  8. Linux信号机制

    Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...

  9. gdb调试段错误及使用

    在编程调试中,经常出现段错误,此时可用gdb调试.具体方法为注册段错误信号处理函数,在处理函数中启动gdb.具体代码如下: void segv_handler(int no) { ]; ]; FILE ...

随机推荐

  1. mysql安装记录

    一.创建mysql用户 useradd mysql 二.解压 tar -zxvf mysql-5.6.38.tar.gz 三.安装依赖包 yum install -y ncurses-devel li ...

  2. ThinkPHP邮件发送S(Smtp + Mail + phpmailer)

    三种邮件发送介绍:(Smtp,Mail以及phpmailer)ThinkPhp 框架下开发. 邮件发送配置先前准备(用该账号做测试用):(这里用新浪邮箱服务器)将自己的新浪邮箱开通 POP3/SMTP ...

  3. JZOJ 4725. 质数序列

    Description 由于去NOI的火车“堵”了数不清时间,小Z和小D打完ETG,闲着无聊开始看今年的JSOI省选题,并尝试着修改题目:对于一个长度为L ≥ 2的序列,X:x1,x2,...,xL ...

  4. 如何用eclipse运行导入的maven项目

    1.配置jdk系统环境变量.找到安装的jdk的安装目录,新建系统环境变量,变量名为JAVA_HOME(作为一个引用),变量值为该路径. 找到Path,将%JAVA_HOME%/bin; 添加到变量值的 ...

  5. 【转】iPhone通讯录AddressBook.framework和AddressBookUI.framework的应用

    通讯录中联系人相关的应用iPhone提供了两个框架:AddressBook.framework和AddressBookUI.framework,使用这两个框架我们可以在程序中访问并显示iPhone数据 ...

  6. North American Invitational Programming Contest (NAIPC) 2017

    (待补) A. Pieces of Parentheses 将括号处理完成后排序,方式参加下面的博客.然后做一遍背包即可. 2018 Multi-University Training Contest ...

  7. Linux命令之---cat

    命令简介 cat命令的用途是连接文件或标准输入并打印.这个命令常用来显示文件内容,或者将几个文件连接起来显示,或者从标准输入读取内容并显示,它常与重定向符号配合使用. 命令格式 cat [选项] [文 ...

  8. Git-起步

    Git命令行 只要输入git,Git就会不带任何参数地列出它的选项和最常用的子命令. 要得到一个完整的git子命令列表,可以输入git help --all 显示版本号 git --version 每 ...

  9. MySQL之架构与历史(一)

    MySQL架构与历史 和其他数据库系统相比,MySQL有点与众不同,它的架构可以在多种不同的场景中应用并发挥好的作用,但同时也会带来一点选择上的困难.MySQL并不完美,却足够灵活,它的灵活性体现在很 ...

  10. 安卓手机关闭底部键盘灯的方法(htc G11亲测有效)

    还在因为看电子书和看电影时键盘灯刺眼而苦恼吗?下面提供一个方法关闭键盘灯,让你轻松DIY! 1、手机必须先Root。使用RE管理器,按照这个路径,找到文件:brightness sys/devices ...