atexit()
:#include <stdlib.h>
void exit_handler(void) {
return;
}
int main () {
atexit(exit_handler);
return 0;
}
当我编译并运行它时:
$ gcc test.c
$ ./a.out
不输出任何内容,这是你所期望的。实际上,当我运行 ldd
时,我得到的结果是:
$ ldd a.out
linux-vdso.so.1 (0x00007fffbe592000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe07d3a8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe07d753000)
然而,libc
似乎没有任何关于 atexit
的符号,只有 __cxa_atexit
和 __cxa_threaded_atexit_impl
:
$ nm --dynamic /lib/x86_64-linux-gnu/libc.so.6 | grep 'atexit'
0000000000037d90 T __cxa_atexit
0000000000037fa0 T __cxa_thread_atexit_impl
正如你所料,如果我尝试动态链接到libc
,我实际上无法调用atexit()
,例如下面的Racket程序,它链接到libc
并尝试查找atexit
:
#lang racket
(require ffi/unsafe)
(get-ffi-obj 'atexit (ffi-lib "libc" '("6")) (_fun (_fun -> _void) -> _int))
输出结果为:
$ racket findatexit.rkt
ffi-obj: couldn't get "atexit" from "libc.so.6" (/lib/x86_64-linux-gnu/libc.so.6: undefined symbol: atexit)
我想知道的是:
1. 如果Linux上的libc没有
atexit
符号,为什么我仍然可以从C程序中调用它?
2. 在Linux上是否有一种动态调用atexit
或类似函数的方法?(我应该注意到,在OS X上,
atexit
似乎是一个符号,所以在这里看起来不寻常。)编辑:
根据@Jonathan的建议,我还运行了:
$ gcc -c test.c
$ nm test.o
U atexit
0000000000000000 T exit_handler
0000000000000007 T main
这似乎表明atexit
符号确实存在,但它并未出现在任何ldd
显示的库中。
gcc -c test.c; nm test.o
命令,查看其中引用的符号。 - Jonathan Leffler$ nm test.o U atexit 0000000000000000 T exit_handler 0000000000000007 T main
- Leif Andersenatexit()
。你是否查看过ld.so.1
(或者对你来说,可能是/lib64/ld-linux-x86-64.so.2
)中的符号?或者可能还有crt0.o
,或者其他链接的文件?你可能需要运行gcc -v test.c
以查看到底链接了哪些库和目标文件。 - Jonathan Leffler$ nm --dynamic /lib64/ld-linux-x86-64.so.2 | grep 'atexit'
- Leif Andersen