Segmentation fault(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機。

原因:查明,,未對指針初始化(未分配起指向的內存空間)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM