首页 技术 正文
技术 2022年11月9日
0 收藏 912 点赞 3,305 浏览 2402 个字

转自: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 ;
}
/******************************程序结束 **********************************/
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,086
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,561
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,410
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,183
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,820
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,903