core dump

http://blog.csdn.net/tenfyguo/article/details/8159176/ubuntu

 

 

一,什麼是coredump 咱們常常聽到你們說到程序core掉了,須要定位解決,這裏說的大部分是指對應程序因爲各類異常或者bug致使在運行過程當中異常退出或者停止,而且在知足必定條件下(這裏爲何說須要知足必定的條件呢?下面會分析)會產生一個叫作core的文件。 一般狀況下,core文件會包含了程序運行時的內存,寄存器狀態,堆棧指針,內存管理信息還有各類函數調用堆棧信息等,咱們能夠理解爲是程序工做當前狀態存儲生成第一個文件,許多的程序出錯的時候都會產生一個core文件,經過工具分析這個文件,咱們能夠定位到程序異常退出的時候對應的堆棧調用等信息,找出問題所在並進行及時解決。 二,coredump文件的存儲位置 core文件默認的存儲位置與對應的可執行程序在同一目錄下,文件名是core,你們能夠經過下面的命令看到core文件的存在位置: cat /proc/sys/kernel/core_pattern 缺省值是core 注意:這裏是指在進程當前工做目錄的下建立。一般與程序在相同的路徑下。但若是程序中調用了chdir函數,則有可能改變了當前工做目錄。這時core文件建立在chdir指定的路徑下。有好多程序崩潰了,咱們卻找不到core文件放在什麼位置。和chdir函數就有關係。固然程序崩潰了不必定都產生 core文件。 以下程序代碼:則會把生成的core文件存儲在/data/coredump/wd,而不是你們認爲的跟可執行文件在同一目錄。 經過下面的命令能夠更改coredump文件的存儲位置,若你但願把core文件生成到/data/coredump/core目錄下: echo 「/data/coredump/core」> /proc/sys/kernel/core_pattern 注意,這裏當前用戶必須具備對/proc/sys/kernel/core_pattern的寫權限。 缺省狀況下,內核在coredump時所產生的core文件放在與該程序相同的目錄中,而且文件名固定爲core。很顯然,若是有多個程序產生core文件,或者同一個程序屢次崩潰,就會重複覆蓋同一個core文件,所以咱們有必要對不一樣程序生成的core文件進行分別命名。 咱們經過修改kernel的參數,能夠指定內核所生成的coredump文件的文件名。例如,使用下面的命令使kernel生成名字爲core.filename.pid格式的core dump文件: echo 「/data/coredump/core.%e.%p」 >/proc/sys/kernel/core_pattern 這樣配置後,產生的core文件中將帶有崩潰的程序名、以及它的進程ID。上面的%e和%p會被替換成程序文件名以及進程ID。 若是在上述文件名中包含目錄分隔符「/」,那麼所生成的core文件將會被放到指定的目錄中。 須要說明的是,在內核中還有一個與coredump相關的設置,就是/proc/sys/kernel/core_uses_pid。若是這個文件的內容被配置成1,那麼即便core_pattern中沒有設置%p,最後生成的core dump文件名仍會加上進程ID。 三,如何判斷一個文件是coredump文件? 在類unix系統下,coredump文件自己主要的格式也是ELF格式,所以,咱們能夠經過readelf命令進行判斷。 能夠看到ELF文件頭的Type字段的類型是:CORE (Core file) 能夠經過簡單的file命令進行快速判斷: 四,產生coredum的一些條件總結 1, 產生coredump的條件,首先須要確認當前會話的ulimit –c,若爲0,則不會產生對應的coredump,須要進行修改和設置。 ulimit -c unlimited (能夠產生coredump且不受大小限制) 若想甚至對應的字符大小,則能夠指定: ulimit –c [size] 能夠看出,這裏的size的單位是blocks,通常1block=512bytes 如: ulimit –c 4 (注意,這裏的size若是過小,則可能不會產生對應的core文件,筆者設置過ulimit –c 1的時候,系統並不生成core文件,並嘗試了1,2,3均沒法產生core,至少須要4才生成core文件) 但當前設置的ulimit只對當前會話有效,若想系統均有效,則須要進行以下設置: Ø 在/etc/profile中加入如下一行,這將容許生成coredump文件 ulimit-c unlimited Ø 在rc.local中加入如下一行,這將使程序崩潰時生成的coredump文件位於/data/coredump/目錄下: echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern 注意rc.local在不一樣的環境,存儲的目錄可能不一樣,susu下可能在/etc/rc.d/rc.local 更多ulimit的命令使用,能夠參考:http://baike.baidu.com/view/4832100.htm 這些須要有root權限, 在ubuntu下每次從新打開中斷都須要從新輸入上面的ulimit命令, 來設置core大小爲無限. 2, 當前用戶,即執行對應程序的用戶具備對寫入core目錄的寫權限以及有足夠的空間。 3, 幾種不會產生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產生的幾種可能狀況 形成程序coredump的緣由有不少,這裏總結一些比較經常使用的經驗吧: 1,內存訪問越界 a) 因爲使用錯誤的下標,致使數組訪問越界。 b) 搜索字符串時,依靠字符串結束符來判斷字符串是否結束,可是字符串沒有正常的使用結束符。 c) 使用strcpy, strcat, sprintf, strcmp,strcasecmp等字符串操做函數,將目標字符串讀/寫爆。應該使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函數防止讀寫越界。 2,多線程程序使用了線程不安全的函數。 應該使用下面這些可重入的函數,它們很容易被用錯: 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,多線程讀寫的數據未加鎖保護。 對於會被多個線程同時訪問的全局數據,應該注意加鎖保護,不然很容易形成coredump 4,非法指針 a) 使用空指針 b) 隨意使用指針轉換。一個指向一段內存的指針,除非肯定這段內存原先就分配爲某種結構或類型,或者這種結構或類型的數組,不然不要將它轉換爲這種結構或類型的指針,而應該將這段內存拷貝到一個這種結構或類型中,再訪問這個結構或類型。這是由於若是這段內存的開始地址不是按照這種結構或類型對齊的,那麼訪問它時就很容易由於bus error而core dump。 5,堆棧溢出 不要使用大的局部變量(由於局部變量都分配在棧上),這樣容易形成堆棧溢出,破壞系統的棧和堆結構,致使出現莫名其妙的錯誤。 六,利用gdb進行coredump的定位 其實分析coredump的工具備不少,如今大部分類unix系統都提供了分析coredump文件的工具,不過,咱們常常用到的工具是gdb。 這裏咱們以程序爲例子來講明如何進行定位。 1, 段錯誤 – segmentfault Ø 咱們寫一段代碼往受到系統保護的地址寫內容。 Ø 按以下方式進行編譯和執行,注意這裏須要-g選項編譯。 能夠看到,當輸入12的時候,系統提示段錯誤而且core dumped Ø 咱們進入對應的core文件生成目錄,優先確認是否core文件格式並啓用gdb進行調試。 從紅色方框截圖能夠看到,程序停止是由於信號11,且從bt(backtrace)命令(或者where)能夠看到函數的調用棧,即程序執行到coremain.cpp的第5行,且裏面調用scanf 函數,而該函數其實內部會調用_IO_vfscanf_internal()函數。 接下來咱們繼續用gdb,進行調試對應的程序。 記住幾個經常使用的gdb命令: l(list) ,顯示源代碼,而且能夠看到對應的行號; b(break)x, x是行號,表示在對應的行號位置設置斷點; p(print)x, x是變量名,表示打印變量x的值 r(run), 表示繼續執行到斷點的位置 n(next),表示執行下一步 c(continue),表示繼續執行 q(quit),表示退出gdb 啓動gdb,注意該程序編譯須要-g選項進行。 注: SIGSEGV 11 Core Invalid memoryreference 七,附註: 1, gdb的查看源碼 顯示源代碼 GDB 能夠打印出所調試程序的源代碼,固然,在程序編譯時必定要加上-g的參數,把源程序信息編譯到執行文件中。否則就看不到源程序了。當程序停下來之後,GDB會報告程序停在了那個文件的第幾行上。你能夠用list命令來打印程序的源代碼。仍是來看一看查看源代碼的GDB命令吧。 list 顯示程序第linenum行的周圍的源程序。 list 顯示函數名爲function的函數的源程序。 list 顯示當前行後面的源程序。 list - 顯示當前行前面的源程序。 通常是打印當前行的上5行和下5行,若是顯示函數是是上2行下8行,默認是10行,固然,你也能夠定製顯示的範圍,使用下面命令能夠設置一次顯示源程序的行數。 setlistsize 設置一次顯示源代碼的行數。 showlistsize 查看當前listsize的設置。 list命令還有下面的用法: list, 顯示從first行到last行之間的源代碼。 list , 顯示從當前行到last行之間的源代碼。 list + 日後顯示源代碼。 通常來講在list後面能夠跟如下這些參數: 行號。 <+offset> 當前行號的正偏移量。 當前行號的負偏移量。 哪一個文件的哪一行。 函數名。 哪一個文件中的哪一個函數。 <*address> 程序運行時的語句在內存中的地址。 2, 一些經常使用signal的含義 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表示「段違例(segmentationviolation)」。 SIGSYS:指示一個無效的系統調用。因爲某種未知緣由,進程執行了一條系統調用指令,但其指示系統調用類型的參數倒是無效的。 SIGTRAP:指示一個實現定義的硬件故障。此信號名來自於PDP-11的TRAP指令。 SIGXCPUSVR4和4.3+BSD支持資源限制的概念。若是進程超過了其軟C P U時間限制,則產生此信號。 SIGXFSZ:若是進程超過了其軟文件長度限制,則SVR4和4.3+BSD產生此信號。 3, Core_pattern的格式 能夠在core_pattern模板中使用變量還不少,見下面的列表: %% 單個%字符 %p 所dump進程的進程ID %u 所dump進程的實際用戶ID %g 所dump進程的實際組ID %s 致使本次core dump的信號 %t core dump的時間 (由1970年1月1日計起的秒數) %h 主機名 %e 程序文件名segmentfault

相關文章
相關標籤/搜索