2014-10-08 77 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處理程序已經消失。

您可以嘗試通過調試器跟蹤執行情況,而不是指出終止發生的位置。