當(dāng)前位置:首頁 > IT技術(shù) > 系統(tǒng)服務(wù) > 正文

Segment fault及LINUX core dump詳解 (zz)
2021-08-10 18:18:02

C 程序在進(jìn)行中發(fā)生segment fault(core dump)錯誤,通常與內(nèi)存操作不當(dāng)有關(guān),主要有以下幾種情況:

(1)數(shù)組越界。

(2)修改了只讀內(nèi)存。

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

……

?

1. 前言:
有的程序可以通過編譯, 但在運行時會出現(xiàn)Segment fault(段錯誤). 這通常都是指針錯誤引起的.
但這不像編譯錯誤一樣會提示到文件->行, 而是沒有任何信息, 使得我們的調(diào)試變得困難起來.


2. gdb:
有一種辦法是, 我們用gdb的step, 一步一步尋找.?
這放在短小的代碼中是可行的, 但要讓你step一個上萬行的代碼, 我想你會從此厭惡程序員這個名字, 而把他叫做調(diào)試員.
我們還有更好的辦法, 這就是core file.


3. ulimit:
如果想讓系統(tǒng)在信號中斷造成的錯誤時產(chǎn)生core文件, 我們需要在shell中按如下設(shè)置:
#設(shè)置core大小為無限
ulimit -c unlimited
#設(shè)置文件大小為無限
ulimit unlimited


這些需要有root權(quán)限, 在ubuntu下每次重新打開中斷都需要重新輸入上面的第一條命令, 來設(shè)置core大小為無限.


4. 用gdb查看core文件:
下面我們可以在發(fā)生運行時信號引起的錯誤時發(fā)生core dump了.
發(fā)生core dump之后, 用gdb進(jìn)行查看core文件的內(nèi)容, 以定位文件中引發(fā)core dump的行.
gdb [exec file] [core file]
如:
gdb ./test test.core
在進(jìn)入gdb后, 用bt命令查看backtrace以檢查發(fā)生程序運行到哪里, 來定位core dump的文件->行.


當(dāng)我們的程序崩潰時,內(nèi)核有可能把該程序當(dāng)前內(nèi)存映射到core文件里,方便程序員找到程序出現(xiàn)問題的地方。最常出現(xiàn)的,幾乎所有C程序員都出現(xiàn)過的錯誤就是“段錯誤”了。也是最難查出問題原因的一個錯誤。下面我們就針對“段錯誤”來分析core文件的產(chǎn)生、以及我們?nèi)绾卫胏ore文件找到出現(xiàn)崩潰的地方。


何謂core文件


當(dāng)一個程序崩潰時,在進(jìn)程當(dāng)前工作目錄的core文件中復(fù)制了該進(jìn)程的存儲圖像。core文件僅僅是一個內(nèi)存映象(同時加上調(diào)試信息),主要是用來調(diào)試的。


當(dāng)程序接收到以下UNIX信號會產(chǎn)生core文件:




名字

?

說明

ANSI C? POSIX.1

SVR4? 4.3+BSD

缺省動作

SIGABRT

異常終止(abort)

? .?????? .

? .????? .

終止w/core

SIGBUS

硬件故障

????????? .

? .????? .

終止w/core

SIGEMT

硬件故障

?

? .????? .

終止w/core

SIGFPE

算術(shù)異常

? .?????? .

? .????? .

終止w/core

SIGILL

非法硬件指令

? .?????? .

? .????? .

終止w/core

SIGIOT

硬件故障

?

? .????? .

終止w/core

SIGQUIT

終端退出符

????????? .

? .????? .

終止w/core

SIGSEGV

無效存儲訪問

? .?????? .

? .????? .

終止w/core

SIGSYS

無效系統(tǒng)調(diào)用

?

? .????? .

終止w/core

SIGTRAP

硬件故障

?

? .????? .

終止w/core

SIGXCPU

超過CPU限制(setrlimit)

?

? .????? .

終止w/core

SIGXFSZ

超過文件長度限制(setrlimit)

?

? .????? .

終止w/core

?



在系統(tǒng)默認(rèn)動作列,“終止w/core”表示在進(jìn)程當(dāng)前工作目錄的core文件中復(fù)制了該進(jìn)程的存儲圖像(該文件名為core,由此可以看出這種功能很久之前就是UNIX功能的一部分)。大多數(shù)UNIX調(diào)試程序都使用core文件以檢查進(jìn)程在終止時的狀態(tài)。


core文件的產(chǎn)生不是POSIX.1所屬部分,而是很多UNIX版本的實現(xiàn)特征。UNIX第6版沒有檢查條件(a)和(b),并且其源代碼中包含如下說明:“如果你正在找尋保護(hù)信號,那么當(dāng)設(shè)置-用戶-ID命令執(zhí)行時,將可能產(chǎn)生大量的這種信號”。4.3 + BSD產(chǎn)生名為core.prog的文件,其中prog是被執(zhí)行的程序名的前1 6個字符。它對core文件給予了某種標(biāo)識,所以是一種改進(jìn)特征。


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


下面比較詳細(xì)地說明這些信號。


? SIGABRT 調(diào)用abort函數(shù)時產(chǎn)生此信號。進(jìn)程異常終止。


? SIGBUS ?指示一個實現(xiàn)定義的硬件故障。


? SIGEMT ?指示一個實現(xiàn)定義的硬件故障。


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


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


? SIGILL ?此信號指示進(jìn)程已執(zhí)行一條非法硬件指令。


4.3BSD由abort函數(shù)產(chǎn)生此信號。SIGABRT現(xiàn)在被用于此。


? SIGIOT ?這指示一個實現(xiàn)定義的硬件故障。


IOT這個名字來自于PDP-11對于輸入/輸出TRAP(input/output TRAP)指令的縮寫。系統(tǒng)V的早期版本,由abort函數(shù)產(chǎn)生此信號。SIGABRT現(xiàn)在被用于此。


? SIGQUIT 當(dāng)用戶在終端上按退出鍵(一般采用Ctrl-)時,產(chǎn)生此信號,并送至前臺進(jìn)


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


? SIGSEGV 指示進(jìn)程進(jìn)行了一次無效的存儲訪問。


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


? SIGSYS ?指示一個無效的系統(tǒng)調(diào)用。由于某種未知原因,進(jìn)程執(zhí)行了一條系統(tǒng)調(diào)用指令,


但其指示系統(tǒng)調(diào)用類型的參數(shù)卻是無效的。


? SIGTRAP 指示一個實現(xiàn)定義的硬件故障。


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


? SIGXCPU SVR4和4.3+BSD支持資源限制的概念。如果進(jìn)程超過了其軟C P U時間限制,則產(chǎn)生此信號。


? SIGXFSZ 如果進(jìn)程超過了其軟文件長度限制,則SVR4和4.3+BSD產(chǎn)生此信號。


摘自《UNIX環(huán)境高級編程》第10章 信號。


?


使用core文件調(diào)試程序


看下面的例子:


/*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


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


執(zhí)行:
?./core_dump_test
段錯誤


運行core_dump_test程序出現(xiàn)了“段錯誤”,但沒有產(chǎn)生core文件。這是因為系統(tǒng)默認(rèn)core文件的大小為0,所以沒有創(chuàng)建??梢杂胾limit命令查看和修改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。


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


可以看到已經(jīng)創(chuàng)建了一個core.6133的文件.6133是core_dump_test程序運行的進(jìn)程ID。


調(diào)式core文件
core文件是個二進(jìn)制文件,需要用相應(yīng)的工具來分析程序崩潰時的內(nèi)存映像。


file core.6133


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


在Linux下可以用GDB來調(diào)試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,就會看到程序崩潰時堆棧信息(當(dāng)前函數(shù)之前的所有已調(diào)用函數(shù)的列表(包括當(dāng)前函數(shù)),gdb只顯示最近幾個),我們很容易找到我們的程序在最后崩潰的時候調(diào)用了core_dump_test.c 第7行的代碼,導(dǎo)致程序崩潰。注意:在編譯程序的時候要加入選項-g。您也可以試試其他命令, 如 fram、list等。更詳細(xì)的用法,請查閱GDB文檔。


core文件創(chuàng)建在什么位置


在進(jìn)程當(dāng)前工作目錄的下創(chuàng)建。通常與程序在相同的路徑下。但如果程序中調(diào)用了chdir函數(shù),則有可能改變了當(dāng)前工作目錄。這時core文件創(chuàng)建在chdir指定的路徑下。有好多程序崩潰了,我們卻找不到core文件放在什么位置。和chdir函數(shù)就有關(guān)系。當(dāng)然程序崩潰了不一定都產(chǎn)生core文件。


什么時候不產(chǎn)生core文件


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


利用GDB調(diào)試core文件,當(dāng)遇到程序崩潰時我們不再束手無策。
名字

?

?

說明

ANSI C? POSIX.1

SVR4? 4.3+BSD

缺省動作

SIGABRT

異常終止(abort)

? .?????? .

? .????? .

終止w/core

SIGBUS

硬件故障

????????? .

? .????? .

終止w/core

SIGEMT

硬件故障

?

? .????? .

終止w/core

SIGFPE

算術(shù)異常

? .?????? .

? .????? .

終止w/core

SIGILL

非法硬件指令

? .?????? .

? .????? .

終止w/core

SIGIOT

硬件故障

?

? .????? .

終止w/core

SIGQUIT

終端退出符

????????? .

? .????? .

終止w/core

SIGSEGV

無效存儲訪問

? .?????? .

? .????? .

終止w/core

SIGSYS

無效系統(tǒng)調(diào)用

?

? .????? .

終止w/core

SIGTRAP

硬件故障

?

? .????? .

終止w/core

SIGXCPU

超過CPU限制(setrlimit)

?

? .????? .

終止w/core

SIGXFSZ

超過文件長度限制(setrlimit)

?

? .????? .

終止w/core

?

本文摘自 :https://blog.51cto.com/u

開通會員,享受整站包年服務(wù)立即開通 >