溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何理解coredump

發(fā)布時(shí)間:2021-11-23 16:28:22 來源:億速云 閱讀:136 作者:柒染 欄目:大數(shù)據(jù)

本篇文章給大家分享的是有關(guān)如何理解coredump,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

一,什么是coredump

        我們經(jīng)常聽到大家說到程序core掉了,需要定位解決,這里說的大部分是指對(duì)應(yīng)程序由于各種異?;蛘遙ug導(dǎo)致在運(yùn)行過程中異常退出或者中止,并且在滿足一定條件下(這里為什么說需要滿足一定的條件呢?下面會(huì)分析)會(huì)產(chǎn)生一個(gè)叫做core的文件。

        通常情況下,core文件會(huì)包含了程序運(yùn)行時(shí)的內(nèi)存,寄存器狀態(tài),堆棧指針,內(nèi)存管理信息還有各種函數(shù)調(diào)用堆棧信息等,我們可以理解為是程序工作當(dāng)前狀態(tài)存儲(chǔ)生成第一個(gè)文件,許多的程序出錯(cuò)的時(shí)候都會(huì)產(chǎn)生一個(gè)core文件,通過工具分析這個(gè)文件,我們可以定位到程序異常退出的時(shí)候?qū)?yīng)的堆棧調(diào)用等信息,找出問題所在并進(jìn)行及時(shí)解決。

二,coredump文件的存儲(chǔ)位置

   core文件默認(rèn)的存儲(chǔ)位置與對(duì)應(yīng)的可執(zhí)行程序在同一目錄下,文件名是core,大家可以通過下面的命令看到core文件的存在位置:

   cat  /proc/sys/kernel/core_pattern

   缺省值是core

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

如下程序代碼:則會(huì)把生成的core文件存儲(chǔ)在/data/coredump/wd,而不是大家認(rèn)為的跟可執(zhí)行文件在同一目錄。

如何理解coredump

通過下面的命令可以更改coredump文件的存儲(chǔ)位置,若你希望把core文件生成到/data/coredump/core目錄下:

   echo “/data/coredump/core”> /proc/sys/kernel/core_pattern

注意,這里當(dāng)前用戶必須具有對(duì)/proc/sys/kernel/core_pattern的寫權(quán)限。

缺省情況下,內(nèi)核在coredump時(shí)所產(chǎn)生的core文件放在與該程序相同的目錄中,并且文件名固定為core。很顯然,如果有多個(gè)程序產(chǎn)生core文件,或者同一個(gè)程序多次崩潰,就會(huì)重復(fù)覆蓋同一個(gè)core文件,因此我們有必要對(duì)不同程序生成的core文件進(jìn)行分別命名。

我們通過修改kernel的參數(shù),可以指定內(nèi)核所生成的coredump文件的文件名。例如,使用下面的命令使kernel生成名字為core.filename.pid格式的core dump文件:

echo “/data/coredump/core.%e.%p” >/proc/sys/kernel/core_pattern

這樣配置后,產(chǎn)生的core文件中將帶有崩潰的程序名、以及它的進(jìn)程ID。上面的%e和%p會(huì)被替換成程序文件名以及進(jìn)程ID。

如果在上述文件名中包含目錄分隔符“/”,那么所生成的core文件將會(huì)被放到指定的目錄中。 需要說明的是,在內(nèi)核中還有一個(gè)與coredump相關(guān)的設(shè)置,就是/proc/sys/kernel/core_uses_pid。如果這個(gè)文件的內(nèi)容被配置成1,那么即使core_pattern中沒有設(shè)置%p,最后生成的core dump文件名仍會(huì)加上進(jìn)程ID。

三,如何判斷一個(gè)文件是coredump文件?

在類unix系統(tǒng)下,coredump文件本身主要的格式也是ELF格式,因此,我們可以通過readelf命令進(jìn)行判斷。

如何理解coredump

     可以看到ELF文件頭的Type字段的類型是:CORE (Core file)

     可以通過簡(jiǎn)單的file命令進(jìn)行快速判斷:     

如何理解coredump

四,產(chǎn)生coredum的一些條件總結(jié)

1,  產(chǎn)生coredump的條件,首先需要確認(rèn)當(dāng)前會(huì)話的ulimit –c,若為0,則不會(huì)產(chǎn)生對(duì)應(yīng)的coredump,需要進(jìn)行修改和設(shè)置。

ulimit  -c unlimited  (可以產(chǎn)生coredump且不受大小限制)

若想甚至對(duì)應(yīng)的字符大小,則可以指定:

ulimit –c [size]

如何理解coredump

       可以看出,這里的size的單位是blocks,一般1block=512bytes

        如:

        ulimit –c 4  (注意,這里的size如果太小,則可能不會(huì)產(chǎn)生對(duì)應(yīng)的core文件,筆者設(shè)置過ulimit –c 1的時(shí)候,系統(tǒng)并不生成core文件,并嘗試了1,2,3均無法產(chǎn)生core,至少需要4才生成core文件)

但當(dāng)前設(shè)置的ulimit只對(duì)當(dāng)前會(huì)話有效,若想系統(tǒng)均有效,則需要進(jìn)行如下設(shè)置:

?  在/etc/profile中加入以下一行,這將允許生成coredump文件

ulimit-c unlimited

?  在rc.local中加入以下一行,這將使程序崩潰時(shí)生成的coredump文件位于/data/coredump/目錄下:

echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern 

注意rc.local在不同的環(huán)境,存儲(chǔ)的目錄可能不同,susu下可能在/etc/rc.d/rc.local

      更多ulimit的命令使用,可以參考:http://baike.baidu.com/view/4832100.htm

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

2, 當(dāng)前用戶,即執(zhí)行對(duì)應(yīng)程序的用戶具有對(duì)寫入core目錄的寫權(quán)限以及有足夠的空間。

3, 幾種不會(huì)產(chǎn)生core文件的情況說明:

The core file will not be generated if

(a)    the process was set-user-ID and the current user is not the owner of the program file, or

(b)     the process was set-group-ID and the current user is not the group owner of the file,

(c)     the user does not have permission to write in the current working directory, 

(d)     the file already exists and the user does not have permission to write to it, or 

(e)     the file is too big (recall the RLIMIT_CORE limit in Section 7.11). The permissions of the core file (assuming that the file doesn't already exist) are usually user-read and user-write, although Mac OS X sets only user-read.

五,coredump產(chǎn)生的幾種可能情況

造成程序coredump的原因有很多,這里總結(jié)一些比較常用的經(jīng)驗(yàn)吧:

 1,內(nèi)存訪問越界

  a) 由于使用錯(cuò)誤的下標(biāo),導(dǎo)致數(shù)組訪問越界。

  b) 搜索字符串時(shí),依靠字符串結(jié)束符來判斷字符串是否結(jié)束,但是字符串沒有正常的使用結(jié)束符。

  c) 使用strcpy, strcat, sprintf, strcmp,strcasecmp等字符串操作函數(shù),將目標(biāo)字符串讀/寫爆。應(yīng)該使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函數(shù)防止讀寫越界。

 2,多線程程序使用了線程不安全的函數(shù)。

應(yīng)該使用下面這些可重入的函數(shù),它們很容易被用錯(cuò):

asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n)ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c) getlogin_r(3c)getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c)fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c)getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3)getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n)nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3)getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c) strtok_r(3c) getgrent_r(3c)getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c)getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)

 3,多線程讀寫的數(shù)據(jù)未加鎖保護(hù)。

對(duì)于會(huì)被多個(gè)線程同時(shí)訪問的全局?jǐn)?shù)據(jù),應(yīng)該注意加鎖保護(hù),否則很容易造成coredump

 4,非法指針

  a) 使用空指針

  b) 隨意使用指針轉(zhuǎn)換。一個(gè)指向一段內(nèi)存的指針,除非確定這段內(nèi)存原先就分配為某種結(jié)構(gòu)或類型,或者這種結(jié)構(gòu)或類型的數(shù)組,否則不要將它轉(zhuǎn)換為這種結(jié)構(gòu)或類型的指針,而應(yīng)該將這段內(nèi)存拷貝到一個(gè)這種結(jié)構(gòu)或類型中,再訪問這個(gè)結(jié)構(gòu)或類型。這是因?yàn)槿绻@段內(nèi)存的開始地址不是按照這種結(jié)構(gòu)或類型對(duì)齊的,那么訪問它時(shí)就很容易因?yàn)閎us error而core dump。

 5,堆棧溢出

不要使用大的局部變量(因?yàn)榫植孔兞慷挤峙湓跅I希?,這樣容易造成堆棧溢出,破壞系統(tǒng)的棧和堆結(jié)構(gòu),導(dǎo)致出現(xiàn)莫名其妙的錯(cuò)誤。  

六,利用gdb進(jìn)行coredump的定位

  其實(shí)分析coredump的工具有很多,現(xiàn)在大部分類unix系統(tǒng)都提供了分析coredump文件的工具,不過,我們經(jīng)常用到的工具是gdb。

  這里我們以程序?yàn)槔觼碚f明如何進(jìn)行定位。

1,  段錯(cuò)誤 – segmentfault

?  我們寫一段代碼往受到系統(tǒng)保護(hù)的地址寫內(nèi)容。

如何理解coredump

?  按如下方式進(jìn)行編譯和執(zhí)行,注意這里需要-g選項(xiàng)編譯。

如何理解coredump

可以看到,當(dāng)輸入12的時(shí)候,系統(tǒng)提示段錯(cuò)誤并且core dumped

?  我們進(jìn)入對(duì)應(yīng)的core文件生成目錄,優(yōu)先確認(rèn)是否core文件格式并啟用gdb進(jìn)行調(diào)試。

如何理解coredump

從紅色方框截圖可以看到,程序中止是因?yàn)樾盘?hào)11,且從bt(backtrace)命令(或者where)可以看到函數(shù)的調(diào)用棧,即程序執(zhí)行到coremain.cpp的第5行,且里面調(diào)用scanf 函數(shù),而該函數(shù)其實(shí)內(nèi)部會(huì)調(diào)用_IO_vfscanf_internal()函數(shù)。

接下來我們繼續(xù)用gdb,進(jìn)行調(diào)試對(duì)應(yīng)的程序。

記住幾個(gè)常用的gdb命令:

l(list) ,顯示源代碼,并且可以看到對(duì)應(yīng)的行號(hào);

b(break)x, x是行號(hào),表示在對(duì)應(yīng)的行號(hào)位置設(shè)置斷點(diǎn);

p(print)x, x是變量名,表示打印變量x的值

r(run), 表示繼續(xù)執(zhí)行到斷點(diǎn)的位置

n(next),表示執(zhí)行下一步

c(continue),表示繼續(xù)執(zhí)行

q(quit),表示退出gdb

啟動(dòng)gdb,注意該程序編譯需要-g選項(xiàng)進(jìn)行。

如何理解coredump

注:  SIGSEGV     11       Core    Invalid memoryreference

七,附注:

1,  gdb的查看源碼

顯示源代碼

GDB 可以打印出所調(diào)試程序的源代碼,當(dāng)然,在程序編譯時(shí)一定要加上-g的參數(shù),把源程序信息編譯到執(zhí)行文件中。不然就看不到源程序了。當(dāng)程序停下來以后,GDB會(huì)報(bào)告程序停在了那個(gè)文件的第幾行上。你可以用list命令來打印程序的源代碼。還是來看一看查看源代碼的GDB命令吧。

list<linenum>

顯示程序第linenum行的周圍的源程序。

list<function>

顯示函數(shù)名為function的函數(shù)的源程序。

list

顯示當(dāng)前行后面的源程序。

list -

顯示當(dāng)前行前面的源程序。

一般是打印當(dāng)前行的上5行和下5行,如果顯示函數(shù)是是上2行下8行,默認(rèn)是10行,當(dāng)然,你也可以定制顯示的范圍,使用下面命令可以設(shè)置一次顯示源程序的行數(shù)。

setlistsize <count>

設(shè)置一次顯示源代碼的行數(shù)。

showlistsize

查看當(dāng)前l(fā)istsize的設(shè)置。

list命令還有下面的用法:

list<first>, <last>

顯示從first行到last行之間的源代碼。

list ,<last>

顯示從當(dāng)前行到last行之間的源代碼。

list +

往后顯示源代碼。

一般來說在list后面可以跟以下這些參數(shù):

<linenum>   行號(hào)。

<+offset>   當(dāng)前行號(hào)的正偏移量。

<-offset>   當(dāng)前行號(hào)的負(fù)偏移量。

<filename:linenum>  哪個(gè)文件的哪一行。

<function>  函數(shù)名。

<filename:function>哪個(gè)文件中的哪個(gè)函數(shù)。

<*address>  程序運(yùn)行時(shí)的語句在內(nèi)存中的地址。

2,  一些常用signal的含義

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

SIGBUS:指示一個(gè)實(shí)現(xiàn)定義的硬件故障。

SIGEMT:指示一個(gè)實(shí)現(xiàn)定義的硬件故障。EMT這一名字來自PDP-11的emulator trap 指令。

SIGFPE:此信號(hào)表示一個(gè)算術(shù)運(yùn)算異常,例如除以0,浮點(diǎn)溢出等。

SIGILL:此信號(hào)指示進(jìn)程已執(zhí)行一條非法硬件指令。4.3BSD由abort函數(shù)產(chǎn)生此信號(hào)。SIGABRT現(xiàn)在被用于此。

SIGIOT:這指示一個(gè)實(shí)現(xiàn)定義的硬件故障。IOT這個(gè)名字來自于PDP-11對(duì)于輸入/輸出TRAP(input/outputTRAP)指令的縮寫。系統(tǒng)V的早期版本,由abort函數(shù)產(chǎn)生此信號(hào)。SIGABRT現(xiàn)在被用于此。

SIGQUIT:當(dāng)用戶在終端上按退出鍵(一般采用Ctrl-/)時(shí),產(chǎn)生此信號(hào),并送至前臺(tái)進(jìn)

程組中的所有進(jìn)程。此信號(hào)不僅終止前臺(tái)進(jìn)程組(如SIGINT所做的那樣),同時(shí)產(chǎn)生一個(gè)core文件。

SIGSEGV:指示進(jìn)程進(jìn)行了一次無效的存儲(chǔ)訪問。名字SEGV表示“段違例(segmentationviolation)”。

SIGSYS:指示一個(gè)無效的系統(tǒng)調(diào)用。由于某種未知原因,進(jìn)程執(zhí)行了一條系統(tǒng)調(diào)用指令,但其指示系統(tǒng)調(diào)用類型的參數(shù)卻是無效的。

SIGTRAP:指示一個(gè)實(shí)現(xiàn)定義的硬件故障。此信號(hào)名來自于PDP-11的TRAP指令。

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

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

3,  Core_pattern的格式

可以在core_pattern模板中使用變量還很多,見下面的列表:

%% 單個(gè)%字符

%p 所dump進(jìn)程的進(jìn)程ID

%u 所dump進(jìn)程的實(shí)際用戶ID

%g 所dump進(jìn)程的實(shí)際組ID

%s 導(dǎo)致本次core dump的信號(hào)

%t core dump的時(shí)間 (由1970年1月1日計(jì)起的秒數(shù))

%h 主機(jī)名

%e 程序文件名

以上就是如何理解coredump,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI