atexit函数详解
#include
int atexit(void (*func) (void)) ;
返回:若成功则为 0,若出错则为非 0
功 能: 注册终止函数(即main执行结束后调用的函数)
C++相关:
在atexit(f)调用之前被静态分配的对象的析构函数将在func()的调用之后被调用。
在一个atexit(func)调用之后建立的这种对象的析构函数将在func的调用之前被调用。
按照 A N S I C 的规定,一个进程可以登记多至 3 2 个函数,这些函数将由 e x i t 自动调用。我们 称 这 些 函 数 为 终 止 处 理 程 序 ( e x i t h a n d l e r ),并用 a t e x i t函 数 来 登 记 这 些 函 数 。
其中, a t e x i t 的 参 数 是 一 个 函 数 地 址 , 当 调 用 此 函 数 时 无 需 向 它 传 送 任 何 参 数 , 也 不 期 望 它 返 回一个值。 e x i t 以 登 记 这 些 函 数 的 相 反 顺 序 调 用 它 们 。 同 一 函 数 如 若 登 记 多 次 , 则 也 被 调 用 多次。
上面是unix环境高级编程的解释。
个人理解:
进程正常结束,会执行atexit提前注册好的函数。
使用这个函数需要注意的几点是:
1.注册过的函数的执行顺序按照栈原则,先进后出,即最先注册的最后执行,最后注册的最先执行。
2.可以注册的函数个数一般多至是32个,具体上限需要根据平台支持,可以使用sysconf函数确定具体上限(此条规则本人没有验证,待后续有时间验证,但目前注册32个没问题,一般也用不到那么多)。
3.必须是进程正常退出时才会调用atexit注册过的函数,若异常退出则不会调用atexit注册过的函数
目前梳理下来的8种进程退出的方式,其中5种会调用atexit函数。
1:从 main 返回
2:调用 exit
3:调用 _exit 或 _Exit
4:最后一个线程从其启动例程返回
5:最后一个线程调用pthread_exit
异常终止有3种:
1:调用 abort
2:接到一个信号并终止
3:最后一个线程对取消请求做出响应
以下是C程序的启动和终止概要图,供理解与参考:
废话不多说,上验证代码。
================以下是验证代码=================
测试代码:
#include
#include
#include
int atexit(void (* funtion) (void));
void fn1(void),fn2(void), fn3(void), fn4(void);
int main(int argc, char const *argv[])
{
printf("main begain!\n");
atexit(fn1);
atexit(fn2);
atexit(fn3);
atexit(fn4);
printf("main exit!\n");
return 0;
}
void fn1()
{
printf("fn1 exit!\n");
}
void fn2()
{
printf("fn2 exit!\n");
}
void fn3()
{
printf("fn3 begain sleep!\n");
sleep(1);
printf("fn3 end sleep!\n");
printf("fn3 exit!\n");
}
void fn4()
{
printf("fn4 exit!\n");
}
运行结果:
main begain!
main exit!
fn4 exit!
fn3 begain sleep!
fn3 end sleep!
fn3 exit!
fn2 exit!
fn1 exit!
main函数修改为exit 退出:
int main(int argc, char const *argv[])
{
printf("main begain!\n");
atexit(fn1);
atexit(fn2);
atexit(fn3);
atexit(fn4);
printf("main exit!\n");
abort();
printf("main return!\n");
return 0;
}
运行结果:
main begain!
main exit!