Segment fault及LINUX core dump詳解

C 程序在進行中發生segment fault(core dump)錯誤,一般與內存操做不當有關,主要有如下幾種狀況:linux

(1)數組越界。程序員

(2)修改了只讀內存。shell

(3)scanf("%d",n),n不是指針。編程

……ubuntu


1. 前言:數組

有的程序能夠經過編譯, 但在運行時會出現Segment fault(段錯誤). 這一般都是指針錯誤引發的.bash

但這不像編譯錯誤同樣會提示到文件->行, 而是沒有任何信息, 使得咱們的調試變得困難起來.函數


2. gdb:工具

有一種辦法是, 咱們用gdb的step, 一步一步尋找. post

這放在短小的代碼中是可行的, 但要讓你step一個上萬行的代碼, 我想你會今後厭惡程序員這個名字, 而把他叫作調試員.

咱們還有更好的辦法, 這就是core file.


3. ulimit:

若是想讓系統在信號中斷形成的錯誤時產生core文件, 咱們須要在shell中按以下設置:

#設置core大小爲無限

ulimit -c unlimited

#設置文件大小爲無限

ulimit unlimited


這些須要有root權限, 在ubuntu下每次從新打開中斷都須要從新輸入上面的第一條命令, 來設置core大小爲無限.


4. 用gdb查看core文件:

下面咱們能夠在發生運行時信號引發的錯誤時發生core dump了.

發生core dump以後, 用gdb進行查看core文件的內容, 以定位文件中引起core dump的行.

gdb [exec file] [core file]

如:

gdb ./test test.core

在進入gdb後, 用bt命令查看backtrace以檢查發生程序運行到哪裏, 來定位core dump的文件->行.


當咱們的程序崩潰時,內核有可能把該程序當前內存映射到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是被執行的程序名的前1 6個字符。它對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/output TRAP)指令的縮寫。系統V的早期版本,由abort函數產生此信號。SIGABRT如今被用於此。

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

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

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

名字SEGV表示「段違例(segmentation violation)」。

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

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

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

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

? SIGXCPU SVR4和4.3+BSD支持資源限制的概念。若是進程超過了其軟C P U時間限制,則產生此信號。

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

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


使用core文件調試程序

看下面的例子:

/*core_dump_test.c*/
 #include <stdio.h>
const char *str = "test";
void core_test(){
    str[1] = 'T';
}
int main(){
    core_test();
    return 0;
}

編譯:

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

-c 指定修改core文件的大小,1000指定了core文件大小。也能夠對core文件的大小不作限制,如:

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 certain conditions.
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, Segmentation fault.
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 () at core_dump_test.c:7
7           str[1] = 'T';
(gdb) where
#0  0x080482fd in core_test () at core_dump_test.c:7
#1  0x08048317 in main () at core_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文件的許可權(假定該文件在此以前並不存在)一般是用戶讀/寫,組讀和其餘讀。

相關文章
相關標籤/搜索