段錯誤 (core dumped) 之 core文件

2011-12-28 10:23
當我們的程序崩潰時,內核有可能把該程序當前內存映射到core文件裏,方便程序員找到程序出現問題的地方。最常出現的,幾乎所有C程序員都出現過的錯誤就是“段錯誤”了。也是最難查出問題原因的一個錯誤。下面我們就針對“段錯誤”來分析core文件的產生、以及我們如何利用core文件找到出現崩潰的地方。 

何謂core文件 
當一個程序崩潰時,在進程當前工作目錄的core文件中複製了該進程的存儲圖像。core文件僅僅是一個內存映象(同時加上調試信息),主要是用來調試的。 
當程序接收到以下UNIX信號會產生core文件:

在系統默認動作列,“終止w/core”表示在進程當前工作目錄的core文件中複製了該進程的存儲圖像(該文件名爲core,由此可以看出這種功能很久之前就是UNIX功能的一部分)。大多數UNIX調試程序都使用core文件以檢查進程在終止時的狀態。 

core文件的產生不是POSIX.1所屬部分,而是很多UNIX版本的實現特徵。UNIX第6版沒有檢查條件(a)和(b),並且其源代碼中包含如下說明:“如果你正在找尋保護信號,那麼當設置-用戶-ID命令執行時,將可能產生大量的這種信號”。4.3+ BSD產生名爲core.prog的文件,其中prog是被執行的程序名的前16個字符。它對core文件給予了某種標識,所以是一種改進特徵。 

表中“硬件故障”對應於實現定義的硬件故障。這些名字中有很多取自UNIX早先在DP-11上的實現。請查看你所使用的系統的手冊,以確切地確定這些信號對應於哪些錯誤類型。 

下面比較詳細地說明這些信號。 

• SIGABRT 調用abort函數時產生此信號。進程異常終止。 

• SIGBUS  指示一個實現定義的硬件故障。 
• SIGEMT  指示一個實現定義的硬件故障。 

EMT這一名字來自PDP-11的emulator trap 指令。 

• SIGFPE 此信號表示一個算術運算異常,例如除以0,浮點溢出等。 

• SIGILL 此信號指示進程已執行一條非法硬件指令。 

4.3BSD由abort函數產生此信號。SIGABRT現在被用於此。 

• SIGIOT  這指示一個實現定義的硬件故障。 

IOT這個名字來自於PDP-11對於輸入/輸出TRAP(input/outputTRAP)指令的縮寫。系統V的早期版本,由abort函數產生此信號。SIGABRT現在被用於此。 

• SIGQUIT當用戶在終端上按退出鍵(一般採用Ctrl-\)時,產生此信號,並送至前臺進 

程組中的所有進程。此信號不僅終止前臺進程組(如SIGINT所做的那樣),同時產生一個core文件。 

• SIGSEGV 指示進程進行了一次無效的存儲訪問。 

名字SEGV表示“段違例(segmentation violation)”。 

• SIGSYS 指示一個無效的系統調用。由於某種未知原因,進程執行了一條系統調用指令, 

但其指示系統調用類型的參數卻是無效的。 

• SIGTRAP 指示一個實現定義的硬件故障。 

此信號名來自於PDP-11的TRAP指令。 

• SIGXCPU SVR4和4.3+BSD支持資源限制的概念。如果進程超過了其軟C PU時間限制,則產生此信號。 

• SIGXFSZ如果進程超過了其軟文件長度限制,則SVR4和4.3+BSD產生此信號。 

摘自《UNIX環境高級編程》第10章 信號。 



使用core文件調試程序 

看下面的例子: 

 
#include<stdio.h> 
char *str = "test"; 
void core_test(){ 
    str[1] ='T'; 


int main(){ 
   core_test(); 
    return0; 


編譯: 
gcc –g core_dump_test.c -o core_dump_test 

如果需要調試程序的話,使用gcc編譯時加上-g選項,這樣調試core文件的時候比較容易找到錯誤的地方。 

執行: 
./core_dump_test 
段錯誤 

運行core_dump_test程序出現了“段錯誤”,但沒有產生core文件。這是因爲系統默認core文件的大小爲0,所以沒有創建。可以用ulimit命令查看和修改core文件的大小。 
ulimit -c 0 
ulimit -c 1000 
ulimit -c 1000 

-c指定修改core文件的大小,1000指定了core文件大小。也可以對core文件的大小不做限制,如: 

ulimit -c unlimited 
ulimit -c unlimited 

如果想讓修改永久生效,則需要修改配置文件,如.bash_profile、/etc/profile或/etc/security/limits.conf。 

再次執行: 
./core_dump_test 
段錯誤 (core dumped) 
ls core.* 
core.6133 

可以看到已經創建了一個core.6133的文件.6133是core_dump_test程序運行的進程ID。 

調式core文件 
core文件是個二進制文件,需要用相應的工具來分析程序崩潰時的內存映像。 

file core.6133 

core.6133: ELF 32-bit LSB core file Intel 80386, version 1 (SYSV),SVR4-style, from 'core_dump_test' 

在Linux下可以用GDB來調試core文件。 

gdb core_dump_test core.6133 

GNU gdb Red Hat Linux(5.3post-0.20021129.18rh) 
Copyright 2003 Free Software Foundation,Inc. 
GDB is free software, covered by the GNU General Public License,and you are 
welcome to change it and/or distribute copies of it under certainconditions. 
Type "show copying" to see the conditions. 
There is absolutely no warranty for GDB.  Type"show warranty" for details. 
This GDB was configured as"i386-redhat-linux-gnu"... 
Core was generated by `./core_dump_test'. 
Program terminated with signal 11, Segmentationfault. 
Reading symbols from/lib/tls/libc.so.6...done. 
Loaded symbols for /lib/tls/libc.so.6 
Reading symbols from/lib/ld-linux.so.2...done. 
Loaded symbols for /lib/ld-linux.so.2 
#0  0x080482fd in core_test () atcore_dump_test.c:7 
7          str[1] = 'T'; 
(gdb) where 
#0  0x080482fd in core_test () atcore_dump_test.c:7 
#1  0x08048317 in main () atcore_dump_test.c:12 
#2  0x42015574 in __libc_start_main () from/lib/tls/libc.so.6 

GDB中鍵入where,就會看到程序崩潰時堆棧信息(當前函數之前的所有已調用函數的列表(包括當前函數),gdb只顯示最近幾個),我們很容易找到我們的程序在最後崩潰的時候調用了core_dump_test.c第7行的代碼,導致程序崩潰。注意:在編譯程序的時候要加入選項-g。您也可以試試其他命令, 如 fram、list等。更詳細的用法,請查閱GDB文檔。 

core文件創建在什麼位置 

在進程當前工作目錄的下創建。通常與程序在相同的路徑下。但如果程序中調用了chdir函數,則有可能改變了當前工作目錄。這時core文件創建在chdir指定的路徑下。有好多程序崩潰了,我們卻找不到core文件放在什麼位置。和chdir函數就有關係。當然程序崩潰了不一定都產生core文件。 

什麼時候不產生core文件 

在下列條件下不產生core文件: 
( a )進程是設置-用戶-ID,而且當前用戶並非程序文件的所有者; 
( b )進程是設置-組-ID,而且當前用戶並非該程序文件的組所有者; 
( c )用戶沒有寫當前工作目錄的許可權; 
( d)文件太大。core文件的許可權(假定該文件在此之前並不存在)通常是用戶讀/寫,組讀和其他讀。 

利用GDB調試core文件,當遇到程序崩潰時我們不再束手無策。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章