linux系統下出現coredump的情況以及除錯方法
什麼是coredump
通常情況下coredmp包括了程式執行時的記憶體,暫存器狀態,堆疊指標,記憶體管理資訊等。能夠理解為把程式工作的當前狀態儲存成一個檔案。很多程式和作業系統出錯時會自己主動生成一個core檔案。
怎樣使用coredump
coredump能夠用在非常多場合,使用Linux,或者solaris的人可能都有過這樣的經歷,系統在跑一些壓力測試或者系統負載一大的話,系統就hang住了或者乾脆system panic.這時唯一能幫助你分析和解決這個問題的就是coredump了。
如今非常多應該程式出錯時也會出現coredump.
分析coredump的工具
如今大部分類unix作業系統都提供了分析core檔案的工具,比方 GNU Binutils Binary File Descriptor library (BFD), GNU Debugger (gdb),mdb等
coredump的檔案格式
類unix作業系統中使用efi格式儲存coredump檔案。
在solairs下
bash-3.2# file *unix.3 ELF 32-bit LSB executable 80386 Version 1, statically linked, not stripped, no debugging information availableunix.4 ELF 32-bit LSB executable 80386 Version 1, statically linked, not stripped, no debugging information available
造成程式coredump的原因非常多,這裡依據以往的經驗總結一下:
1 記憶體訪問越界
a) 因為使用錯誤的下標,導致陣列訪問越界
b) 搜尋字串時,依靠字串結束符來推斷字串是否結束,可是字串沒有正常的使用結束符
c) 使用strcpy, strcat, sprintf, strcmp, strcasecmp等字串操作函式,將目標字串讀/寫爆。應該使用strncpy, strlcpy, strncat, strlcat, snprintf, strncmp, strncasecmp等函式防止讀寫越界。
2 多執行緒程式使用了執行緒不安全的函式。
應該使用以下這些可重入的函式,尤其注意紅色標示出來的函式,它們非常easy被用錯:
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 多執行緒讀寫的資料未加鎖保護。
對於會被多個執行緒同一時候訪問的全域性資料,應該注意加鎖保護,否則非常easy造成core dump
4 非法指標
a) 使用空指標
b) 任意使用指標轉換。一個指向一段記憶體的指標,除非確定這段記憶體原先就分配為某種結構或型別,或者這樣的結構或型別的陣列,否則不要將它轉換為這樣的結構或型別 的指標,而應該將這段記憶體複製到一個這樣的結構或型別中,再訪問這個結構或型別。這是由於假設這段記憶體的開始地址不是依照這樣的結構或型別對齊的,那麼訪問它 時就非常easy由於bus error而core dump.
5 堆疊溢位
不要使用大的區域性變數(由於區域性變數都分配在棧上),這樣easy造成堆疊溢位,破壞系統的棧和堆結構,導致出現莫名其妙的錯誤。
coredump檔案的生成方法以及用法:
(如果下例是在x86上交叉編譯,而在arm上執行異常的現象)
1. 在arm核心裡添?coredump的支援(一般核心都支援coredump, 不用重編)
2. 執行命令,此時同意coredump檔案產生:(在arm上)
ulimit –c unlimited
3. 執行程式:(在arm上)
./test
在異常退出時,會顯演示樣例如以下資訊,注意括號中的內容
Segmentation fault (core dumped)
程式執行資料夾下將產生*core檔案
4. 用gdb分析:(在x86上)
arm-linux-gdb ./test test.core
再用gdb的bt或where看就能夠了
(arm-linux-gdb的編譯見<除錯工具之四gdbserve>)
系統支援生成core並設定儲存位置的方法:
1> 在/etc/profile中添?下面一行,這將同意生成coredump檔案
ulimit -c unlimited
2> 在rc.local中添?下面一行,這將使程式崩潰時生成的coredump檔案位於/tmp資料夾下:
echo /tmp/core.%e.%p > /proc/sys/kernel/core_pattern
/tmp/也能夠是其他的資料夾位置。最佳位置應當滿足下面需求:
* 對全部使用者可寫
* 空間容量足夠大
* 掉電後文件不丟失