+ -
当前位置:首页 → 问答吧 → atexit()问题~

atexit()问题~

时间:2010-07-05

来源:互联网

哪位大侠帮忙解释下 atexit()函数是在main()结束前执行呢还是在结束之后执行呢???

作者: 单眼皮大姐   发布时间: 2010-07-05

man 3 exit

作者: 没本   发布时间: 2010-07-05

本帖最后由 没本 于 2010-07-06 00:36 编辑

如果你又问:那么exit()是在main()之后执行的么?
我只能建议你做如下实验:
  1. $ echo "int main(){return 0;}" > test.c
  2. $ gcc -g -o test test.c
  3. $ gdb test
  4. GNU gdb (GDB) 7.1
  5. Copyright (C) 2010 Free Software Foundation, Inc.
  6. License GPLv3+: GNU GPL version 3 or later <[url]http://gnu.org/licenses/gpl.html[/url]>
  7. This is free software: you are free to change and redistribute it.
  8. There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
  9. and "show warranty" for details.
  10. This GDB was configured as "i686-pc-linux-gnu".
  11. For bug reporting instructions, please see:
  12. <[url]http://www.gnu.org/software/gdb/bugs/[/url]>...
  13. Reading symbols from /home/foo/tmp/test...done.
  14. (gdb) b exit
  15. Function "exit" not defined.
  16. Make breakpoint pending on future shared library load? (y or [n]) y

  17. Breakpoint 1 (exit) pending.
  18. (gdb) b main
  19. Breakpoint 2 at 0x8048377: file test.c, line 1.
  20. (gdb) r
  21. Starting program: /home/foo/tmp/test

  22. Breakpoint 2, main () at test.c:1
  23. 1       int main(){return 0;}
  24. (gdb) n
  25. 0xb7e95c76 in __libc_start_main () from /lib/libc.so.6
  26. (gdb) c
  27. Continuing.

  28. Breakpoint 1, 0xb7eace14 in exit () from /lib/libc.so.6
  29. (gdb) c
  30. Continuing.

  31. Program exited normally.
  32. (gdb)
复制代码
相信科学,远离邪+教。

作者: 没本   发布时间: 2010-07-06

另一佐证:
__libc_start_main

Name

__libc_start_main -- initialization routine
Synopsis

int __libc_start_main(int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end));

Description

The __libc_start_main() function shall perform any necessary initialization of the execution environment, call the main function with appropriate arguments, and handle the return from main(). If the main() function returns, the return value shall be passed to the exit() function.

Note: While this specification is intended to be implementation independent, process and library initialization may include:

performing any necessary security checks if the effective user ID is not the same as the real user ID.

initialize the threading subsystem.

registering the rtld_fini to release resources when this dynamic shared object exits (or is unloaded).

registering the fini handler to run at program exit.

calling the initializer function (*init)().

calling main() with appropriate arguments.

calling exit() with the return value from main().

This list is an example only.
__libc_start_main() is not in the source standard; it is only in the binary standard.

See Also

The section on Process Initialization in each of the architecture specific supplements.

作者: 没本   发布时间: 2010-07-06

理论上说:

1. 标准要求main返回等效于调用exit
c99 5.1.2.2.3 Program termination

2. exit首先会调用atexit注册的函数
c99 7.20.4.3 The exit function


从实践出发:

1. 可以写个程序大致猜测
  1. #include <stdlib.h>
  2. int main() {
  3.       struct local {
  4.             ~local() { printf("before return\n"); }
  5.       static void onexit() { printf("in atexit\n"); }
  6.       } l;
  7.       atexit(&local::onexit);
  8.       return 0;
  9. }
复制代码
2. 查看进程启动代码

进程、线程的启动代码都是如下形式:
  1. exit( main( argc, argv ) );
  2. _endthreadex( thread_routine(arg) );
复制代码
这是如何保证main返回等效于调用exit的方法。
这里可以看出, exit是在main返回之后, 以main的返回值来调用。
从这里也可以看出, 最好是让main或者线程函数返回到它们的caller, 然后由caller余下部分的代码调用exit或者_endthreadex。

如果直接调用exit或_endthreadex, 从调用点到这个启动main或线程的caller之间的frame的清理工作就不会被执行。

作者: OwnWaterloo   发布时间: 2010-07-06