退出时的回调函数: atexit, signal

工具函数: atexit, signal
在嵌入式调试中,经常有segment_fault, 但却没有core_dump(当然ulimit是打开的),此时应该怎样调试?
第一种(常规办法), 从main 开始单步跟踪函数找到问题点
第二种(查看崩溃时的调用堆栈), 可是core_dump 没有生成,如何查看呢?
然后我们在回调函数中打印出当前的函数调用栈,就可以知道程序在哪里退出了.


1. 正常退出, 调用atexit()函数,安装exit 时的回调函数
程序的正常退出会调用exit()函数
不过exit 是c 库函数,我们最好中断到我们自己的函数中,所以,
在程序开始时,通过系统提供的atexit(),向系统注册一个回调函数,在程序调用exit()退出的时候,exit会调用这个回调函数就,

使用atexit函数。
头文件:#include <stdlib.h>,
函数原型:int atexit(void (*func)(void));
atexit可以调用多次,注册多个回调函数,在进程退出时调用.

2. 异常退出, 调用signal(), 安装信号处理器
相应某些signal 的默认处理是异常退出,处理方法是使用signal 函数, 注册自己的回调函数,避免系统默认回调,
因为系统的默认回调往往是杀死进程, 下面是常用的信号处理框架!

#include <signal.h>
void before_exit(void)
{
    printf("that's all, folks!\n");
}
void crash_handler(int sig)
{
    printf("crash_handler! sig is %d\n",sig);
    exit(-1);  //exit 会回调before_exit, 因为已经注册
}

void signal_exit_handler(int sig)
{
    exit(0);
}

int main(int argc, char *argv[])
{
    atexit(before_exit);
    signal(SIGTERM, signal_exit_handler);
    signal(SIGINT, signal_exit_handler);

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);

    signal(SIGBUS, crash_handler);     // 总线错误
    signal(SIGSEGV, crash_handler);    // SIGSEGV,非法内存访问
    signal(SIGFPE, crash_handler);       // SIGFPE,数学相关的异常,如被0除,浮点溢出,等等
    signal(SIGABRT, crash_handler);     // SIGABRT,由调用abort函数产生,进程非正常退出

    return 0;
}

3. 段错误退出,
    这只是异常退出的一个特例, 该方法可以做为<segment_fault 的一种处理方法>(另一篇博客)的更完善补充
    只所以单独来说,是因为它太普遍了.
    signal(SIGSEGV, crash_handler);    // SIGSEGV,非法内存访问
实例:

#include <stdio.h>
#include <signal.h>

void crash_handler(int sig)
{
    (void) sig;
    printf("crash_handler!\n");
}
int test_crash2(int *p)
{
    int i;
    i=*p;  // 此句会引起segment fault, 该segment falut事件会激发signal,并回调crash_handler
    return i;
}

int test_crash(int *p)
{
    int j;
    j=test_crash2(p);
    return j;
}

int main()
{
    signal(SIGSEGV, crash_handler);    //安装segment fault 事件处理器
    printf("hello\n");
    int k = test_crash(0);  // 传入一个非法地址
    printf("k is %d\n",k);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值