我有一个在Linux上意外退出的C程序,我很难找到原因(没有核心转储,请参阅XIO: fatal IO error 11)。我在程序的开头放置了一个atexit(),并且在发生崩溃时确实调用了回调函数。
我怎么知道什么称为atexit回调函数?从阅读手册页开始,在退出时调用atexit(d' ho!)或从main返回。我可以排除后者,因为在主要的末尾有一堆printf,我不会看到它们。我可以排除前者,因为我的程序中没有任何exit()。
只留下一个解决方案:从库函数调用exit。这是唯一的可能性吗?我怎么知道从哪里来?是否可以打印堆栈跟踪或从atexit回调中强制核心转储?
答案 0 :(得分:5)
致电,例如你的atexit处理程序中的abort(),并检查gdb中的coredump。如果运行atexit处理程序,gdb backtrace命令会显示它退出的位置。这是一个演示:
#include <stdlib.h>
void exit_handler(void)
{
abort();
}
void startup()
{
#ifdef DO_EXIT
exit(99);
#endif
}
int main(int argc, char *argv[])
{
atexit(exit_handler);
startup();
return 0;
}
这样做:
$ gcc -DDO_EXIT -g atexit.c
$ ulimit -c unlimited
$ ./a.out
Aborted (core dumped)
$ gdb ./a.out core.28162
GNU gdb (GDB) Fedora 7.7.1-19.fc20
..
Core was generated by `./a.out'.
Program terminated with signal SIGABRT, Aborted.
#0 0xb77d7424 in __kernel_vsyscall ()
Missing separate debuginfos, use: debuginfo-install glibc-2.18-16.fc20.i686
(gdb) bt
#0 0xb77d7424 in __kernel_vsyscall ()
#1 0x42e1a8e7 in raise () from /lib/libc.so.6
#2 0x42e1c123 in abort () from /lib/libc.so.6
#3 0x0804851b in exit_handler () at atexit.c:6
#4 0x42e1dd61 in __run_exit_handlers () from /lib/libc.so.6
#5 0x42e1ddbd in exit () from /lib/libc.so.6
#6 0x0804852d in startup () at atexit.c:12
#7 0x08048547 in main (argc=1, argv=0xbfc39fb4) at atexit.c:21
正如预期的那样,它显示startup()调用exit。
你也可以交互式地调试这个,在gdb中启动你的程序并在atexit处理程序中设置一个断点。
答案 1 :(得分:1)
标准只说#34;正常程序终止&#34;,所以在Linux上,这可能超过exit
或return
来自main
。你也忘了pthread_exit
,它也可以终止main
的线程,从而终止整个程序。
在任何情况下,都无法立即查看终止发布的位置。 atexit
处理程序通常由初始化函数调用。根据定义,所有其他应用程序代码,但atexit
处理程序在那时消失了。
您可以尝试通过调试器跟踪执行情况,无法确定终止发生的位置。