有时候,我们期望在进程退出时做一些资源清理工作,比如释放共享内存、删除程序运行期间留下的一些临时文件等等。
一种方式是使用 __attribute__ 关键字将清理函数声明为 destructor 函数:
1 2 3 4 5 6 7 8 9 10 11 12 | #include <stdio.h> #include <stdlib.h> __attribute__((destructor)) void cleanup() { printf("%s\n", __func__); } int main() { printf("%s\n", __func__); return 0; } |
这样该清理函数就会在 main 函数结束后被执行。
1 2 3 | $ ./a.out main cleanup |
另外一种方式是使用 atexit 函数注册清理函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <stdio.h> #include <stdlib.h> __attribute__((constructor)) void func() { printf("%s\n", __func__); atexit([](){printf("global cleaner\n");}); } int main() { printf("%s\n", __func__); atexit([]() {printf("main cleaner\n");}); return 0; } |
如上,在声明为 constructor 的 func 函数和 main 函数里面,通过 atexit 分别注册了两个匿名的清理函数,执行结果如下:
1 2 3 4 5 | $ ./a.out func main main cleanner global cleanner |
首先是 constructor 函数被执行,然后是 main 函数,接着是 main 函数注册的清理函数,最后是 constructor 函数注册的清理函数。这说明通过 atexit 注册的清理函数,其执行顺序是跟注册严格反序的,也就是最后注册的最先执行。
另外,值得注意的是,c++ 限制通过 atexit 最多可以注册 32 个清理函数。
发表回复