2014-10-08 37 views
1

我有一个C程序,在Linux上意外退出,我很难找出原因(没有核心转储,请参见XIO: fatal IO error 11)。我在程序的开头放置了一个atexit()函数,发生崩溃时确实调用了回调函数。谁叫atexit()?

如何知道什么叫做atexit回调函数?从阅读手册页,atexit在退出(d'ho!)或从主返回时被调用。我可以排除后者,因为在主结束处有一堆printf,我没有看到它们。我可以排除前者,因为我的程序中没有任何exit()。

这只剩下一个解决方案:从库函数调用exit。这是唯一的可能吗?我怎么能从哪里知道?是否有可能打印出一个堆栈跟踪或从atexit回调中强制核心转储?

+2

您定位了哪个平台? Windows,Linux,其他?我们可能会找到特定的API函数来帮助您。 – blue112 2014-10-08 12:34:42

+2

“我有一个C程序,在Linux上意外退出”我猜他是针对Linux? – MrSykkox 2014-10-08 12:48:35

+0

在当前的'atexit'函数中放入*真*坏的东西。除以零?堆叠/下溢?内存分配失败? (不幸的是,我只是偶然得到这些错误,从来没有故意,所以我不能特别推荐任何方法。) – usr2564301 2014-10-08 12:55:42

回答

5

打电话给在你的atexit处理程序中放弃(),并检查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 

正如预期的那样,它显示了启动()调用exit。

你也可以交互地调试它,在gdb中启动你的程序并在atexit处理程序中设置一个断点。

+0

谢谢。我不知道中止功能。 – dargaud 2014-10-09 09:49:20

1

该标准只说“在正常程序终止”,所以也许在Linux上这比mainexitreturn。你也忘了pthread_exit,这也可能会终止main的线程,从而整个程序。

在任何情况下,都无法立即从发出终止的地方看到。处理程序通常由初始化函数调用。根据定义,所有其他应用程序代码,但atexit处理程序已经消失。

您可以尝试通过调试器跟踪执行情况,而不是指出终止发生的位置。