有的程序能夠經過編譯,但在運行時會出現Segment fault(段錯誤)。這一般都是指針錯誤引發的。但這不像編譯錯誤同樣會提示到文件一行,而是沒有任何信息。一種辦法是用gdb的step, 一步一步尋找。但要step一個上萬行的代碼讓人不可思議。 咱們還有更好的辦法,這就是core file。mysql
若是想讓系統在信號中斷形成的錯誤時產生core文件, 咱們須要在shell中按以下設置:linux
#設置core大小爲無限 ulimit -c unlimitedsql
#設置文件大小爲無限 ulimit unlimitedshell
發生core dump以後,用gdb進行查看core文件的內容, 以定位文件中引起core dump的行:bash
gdb [exec file] [core file]app
如: gdb ./test test.core 在進入gdb後, 用bt命令查看backtrace以檢查發生程序運行到哪裏,來定位core dump的文件->行。ide
另外須要注意的是,若是你的機器上跑不少的應用,你生成的core又不知道是哪一個應用產生的,你能夠經過下列命令進行查看:file coreui
幾個問題:spa
1. 什麼是Core:操作系統
在使用半導體做爲內存的材料前,人類是利用線圈看成內存的材料(發明者爲王安),線圈就叫做 core ,用線圈作的內存就叫做 core memory。現在 ,半導體工業澎勃發展,已經沒有人用 core memory 了,不過,在許多狀況下,人們仍是把記憶體叫做 core 。
2. 什麼是Core Dump:
咱們在開發(或使用)一個程序時,最怕的就是程序莫明其妙地當掉。雖然系統沒事,但咱們下次仍可能遇到相同的問題。因而這時操做系統就會把程序當掉 時的內存內容 dump 出來(如今一般是寫在一個叫 core 的 file 裏面),讓 咱們或是 debugger 作爲參考。這個動做就叫做 core dump。
3. Core Dump時會生成何種文件:
Core Dump時,會生成諸如 core.進程號 的文件。
4. 爲什麼有時程序Down了,卻沒生成 Core文件。
Linux下,有一些設置,標明瞭resources available to the shell and to processes。 可使用
#ulimit -a 來看這些設置。 (ulimit是bash built-in Command)
從這裏能夠看出,若是 -c是顯示:core file size。若是這個值爲0,則沒法生成core文件。因此可使用:#ulimit -c 1024 或者 #ulimit -c unlimited 來使能 core文件。若是程序出錯時生成Core 文件,則會顯示Segmentation fault (core dumped) 。
5. Core Dump的核心轉儲文件目錄和命名規則:
/proc/sys/kernel /core_uses_pid能夠控制產生的core文件的文件名中是否添加pid做爲擴展,若是添加則文件內容爲1,不然爲0
可經過如下命令修改此文件:
echo "1" > /proc/sys/kernel/core_uses_pid
6. 如何使用Core文件:
在linux下,使用:
#gdb -c core.pid program_name
就能夠進入gdb模式。
輸入where,就能夠指出是在哪一行被Down掉,哪一個function內,由誰調用等等。
(gdb) where
或者輸入 bt。
(gdb) bt
7. 如何讓一個正常的程序down:
#kill -s SIGSEGV pid
8. 察看Core文件輸出在何處:
存放Coredump的目錄即進程的當前目錄,通常就是當初發出命令啓動該進程時所在的目錄。但若是是經過腳本啓動,則腳本可能會修改當前目錄,這時進程真正的當前目錄就會與當初執行腳本所在目錄不一樣。這時能夠查看」/proc/<進程pid>/cwd「符號連接的目標來肯定進程真正的當前目錄地址。經過系統服務啓動的進程也可經過這一方法查看。
proc/sys/kernel /core_pattern能夠控制core文件保存位置和文件名格式。
可經過如下命令修改此文件:
echo "/corefile/core-%e-%p-%t" >core_pattern
能夠將core文件統一輩子成到/corefile目錄下,產生的文件名爲core-命令名-pid-時間戳
如下是參數列表:
%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加當前uid
%g - insert current gid into filename 添加當前gid
%s - insert signal that caused the coredump into the filename 添加致使產生core的信號
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成時的unix時間
%h - insert hostname where the coredump happened into filename 添加主機名
%e - insert coredumping executable name into filename 添加命令名
在Linux下要保證程序崩潰時生成 Coredump要注意這些問題:
1、要保證存放Coredump的目錄存在且進程對該目錄有寫權限。存放Coredump 的目錄即進程的當前目錄,通常就是當初發出命令啓動該進程時所在的目錄。但若是是經過腳本啓動,則腳本可能會修改當前目錄,這時進程真正的當前目錄就會與當初執行腳本所在目錄不一樣。這時能夠查看」/proc/進程pid>/cwd「符號連接的目標來肯定進程真正的當前目錄地址。經過系統服務啓動的進程也可經過這一方法查看。
2、若程序調用了seteuid()/setegid()改變了進程的有效用戶或組,則在默認狀況下系統不會爲這些進程生成Coredump。不少服務程序都會調用seteuid(),如MySQL,不論你用什麼用戶運行 mysqld_safe啓動mysql,mysqld進行的有效用戶始終是msyql用戶。若是你當初是以用戶A運行了某個程序,但在ps裏看到的這個程序的用戶倒是B的話,那麼這些進程就是調用了seteuid了。爲了可以讓這些進程生成core dump,須要將/proc/sys/fs
/suid_dumpable 文件的內容改成1(通常默認是0)。
3、這個通常都知道,就是要設置足夠大的Core文件大小限制了。程序崩潰時生成的 Core文件大小即爲程序運行時佔用的內存大小。但程序崩潰時的行爲不可按日常時的行爲來估計,好比緩衝區溢出等錯誤可能致使堆棧被破壞,所以常常會出現某個變量的值被修改爲亂七八糟的,而後程序用這個大小去申請內存就可能致使程序比日常時多佔用不少內存。所以不管程序正常運行時佔用的內存多麼少,要保證生成Core文件仍是將大小限制設爲unlimited爲好。
4、異常退出就必定會生成core嗎? 難道沒有不生成core的異常退出?
若是不是正常退出的那就是有信號引發的程序退出,有些信號確實能引發程序退出但不生成core。
SIGHUP 終止進程 終端線路掛斷
SIGINT 終止進程 中斷進程
SIGQUIT 創建CORE文件終止進程,而且生成core文件
SIGILL 創建CORE文件 非法指令
SIGTRAP 創建CORE文件 跟蹤自陷
SIGBUS 創建CORE文件 總線錯誤
SIGSEGV 創建CORE文件 段非法錯誤
SIGFPE 創建CORE文件 浮點異常
SIGIOT 創建CORE文件 執行I/O自陷
SIGKILL 終止進程 殺死進程
SIGPIPE 終止進程 向一個沒有讀進程的管道寫數據
SIGALARM 終止進程 計時器到時
SIGTERM 終止進程 軟件終止信號
SIGSTOP 中止進程 非終端來的中止信號
SIGTSTP 中止進程 終端來的中止信號
SIGCONT 忽略信號 繼續執行一箇中止的進程
SIGURG 忽略信號 I/O緊急信號
SIGIO 忽略信號 描述符上能夠進行I/O
SIGCHLD 忽略信號 當子進程中止或退出時通知父進程
SIGTTOU 中止進程 後臺進程寫終端
SIGTTIN 中止進程 後臺進程讀終端
SIGXGPU 終止進程 CPU時限超時
SIGXFSZ 終止進程 文件長度過長
SIGWINCH 忽略信號 窗口大小發生變化
SIGPROF 終止進程 統計分佈圖用計時器到時
SIGUSR1 終止進程 用戶定義信號1
SIGUSR2 終止進程 用戶定義信號2
SIGVTALRM 終止進程 虛擬計時器到
把可能的信號都設置上句柄,看是那種狀況。
Segmentation fault(段錯誤)是因爲虛擬內存管理單元的異常所致,而該異常則一般是因爲解引用一個未初始化或非法值的指針引發的。
Linux中提供了core dump的功能,使得對這類錯誤的調試更爲容易。
通常狀況下,linux系統是不容許產生core文件的,所以首先要解除這個限制:
ulimit -c unlimited
接下來,運行含segmentation fault的段程序,如:
./test
這時,segmentation fault的錯誤信息會顯示爲:
Segmentation fault (core dumped)
在該文件夾下會出現一個名爲core的文件
使用生成的core文件進行調試
gdb test core
(gdb) bt
#0 0x00a5c920 in ?? () from /lib/i386-linux-gnu/libc.so.6#1 0x00a5ca0d in exit () from /lib/i386-linux-gnu/libc.so.6#2 0x00a4311b in __libc_start_main () from /lib/i386-linux-gnu/libc.so.6#3 0x080483d1 in _start ()