什麼是Segmentation fault(Core Dump)? + 我遇到的例項問題

fiona8953發表於2016-11-01

什麼是Core Dump?
Core的意思是記憶體, Dump的意思是扔出來, 堆出來.
開發和使用Unix程式時, 有時程式莫名其妙的down了, 卻沒有任何的提示(有時候會提示core dumped). 這時候可以檢視一下有沒有形如core.程式號的檔案生成, 這個檔案便是作業系統把程式down掉時的記憶體內容扔出來生成的, 它可以做為除錯程式的參考.
core dump又叫核心轉儲, 當程式執行過程中發生異常, 程式異常退出時, 由作業系統把程式當前的記憶體狀況儲存在一個core檔案中, 叫core dump.

如何使用core檔案?
gdb -c core檔案路徑 [應用程式的路徑]
進去後輸入where回車, 就可以顯示程式在哪一行down掉的, 在哪個函式中.

為什麼沒有core檔案生成呢?
有時候程式down了, 但是core檔案卻沒有生成. core檔案的生成跟你當前系統的環境設定有關係, 可以用下面的語句設定一下, 然後再執行程式便成生成core檔案.
ulimit -c unlimited
沒有找到core檔案,我們改改ulimit的設定,讓它產生。1024是隨便取的,要是core檔案大於1024個塊,就產生不出來了。)
$ ulimit -c 1024 (轉者注: 使用-c unlimited不限制core檔案大小

core檔案生成的位置一般於執行程式的路徑相同, 檔名一般為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 dump的原因很多,這裡根據以往的經驗總結一下:

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 多執行緒讀寫的資料未加鎖保護。

對於會被多個執行緒同時訪問的全域性資料,應該注意加鎖保護,否則很容易造成core dump


4 非法指標

  a) 使用空指標

  b) 隨意使用指標轉換。一個指向一段記憶體的指標,除非確定這段記憶體原先就分配為某種結構或型別,或者這種結構或型別的陣列,否則不要將它轉換為這種結構或型別的指標,而應該將這段記憶體複製到一個這種結構或型別中,再訪問這個結構或型別。這是因為如果這段記憶體的開始地址不是按照這種結構或型別對齊的,那麼訪問它時就很容易因為bus error而core dump.


5 堆疊溢位

不要使用大的區域性變數(因為區域性變數都分配在棧上),這樣容易造成堆疊溢位,破壞系統的棧和堆結構,導致出現莫名其妙的錯誤。

============================================================================

我發生的問題(待解決中):

main.h:
typedef struct TS_PAT
{
  UINT8 table_id;
  UINT32 zero;
} TS_PAT;

main.c:
TS_PAT *PAT_DataTable;

void Load_PAT_table(FILE *stream){
    PAT_DataTable->table_id = 1;
}
上記程式碼,編譯透過。


執行時:
Segmentation fault(core dumped)


用上記方法,最後的bt命令輸入後:
#0  0x080486e7 in Load_PAT_table (stream=0x804c050) at main.c:76
76              PAT_DataTable->table_id = 1;
(gdb) bt
#0  0x080486e7 in Load_PAT_table (stream=0x804c050) at main.c:76
#1  0x080487a5 in Parse_Adjust_PAT_table (stream=0x804c050) at main.c:137
#2  0x08049651 in main (argn=3, argc=0xbf96e284) at main.c:827

當註釋掉”PAT_DataTable->table_id = 1;“的時候,沒問題。
否則,在這行賦值語句執行時就down機。

原因:查明,,未對指標初始化(未分配起指向的記憶體空間)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26477398/viewspace-2127432/,如需轉載,請註明出處,否則將追究法律責任。

相關文章