gdb調試core文件夾
『壹』 怎樣用GDB調試一個由腳本文件啟動的程序
使用GDB
一般來說GDB主要調試的是C/C++的程序。要調試C/C++的程序,首先在編譯時,我們必須要把調試信息加到可執行文件中。使用編譯器(cc/gcc/g++)的 -g 參數可以做到這一點。如:
$gcc -g -Wall hello.c -o hello
$g++ -g -Wall hello.cpp -o hello
如果沒有-g,你將看不見程序的函數名、變數名,所代替的全是運行時的內存地址。當你用-g把調試信息加入之後,並成功編譯目標代碼以後,讓我們來看看如何用gdb來調試他。
啟動GDB的方法有以下幾種:
gdb <program>
program也就是你的執行文件,一般在當前目錄下。
gdb <program> core
用gdb同時調試一個運行程序和core文件,core是程序非法執行後core mp後產生的文件。
gdb <program> <PID>
如果你的程序是一個服務程序,那麼你可以指定這個服務程序運行時的進程ID。gdb會自動attach上去,並調試他。program應該在PATH環境變數中搜索得到。
以上三種都是進入gdb環境和載入被調試程序同時進行的。也可以先進入gdb環境,在載入被調試程序,方法如下:
*在終端輸入:gdb
*在gdb環境中:file <program>
這兩步等價於:gdb <program>
GDB啟動時,可以加上一些GDB的啟動開關,詳細的開關可以用gdb -help查看。我在下面只例舉一些比較常用的參數:
-symbols <file>
-s <file>
從指定文件中讀取符號表。
-se file
從指定文件中讀取符號表信息,並把他用在可執行文件中。
-core <file>
-c <file>
調試時core mp的core文件。
-directory <directory>
-d <directory>
加入一個源文件的搜索路徑。默認搜索路徑是環境變數中PATH所定義的路徑。
『貳』 怎樣用GDB調試core文件
一般這種情況都是因為數組越界訪問,空指針或是野指針讀寫造成的。程序小的話還比較好辦,對著源代碼仔細檢查就能解決。但是對於代碼量較大的程序,里邊包含N多函數調用,N多數組指針訪問,這時想定位問題就不是很容易了(此時牛人依然可以通過在適當位置打printf加二分查找的方式迅速定位:P)。懶人的話還是直接GDB搞起吧。 神馬是Core Dump文件偶爾就能聽見某程序員同學抱怨「擦,又出Core了!」。簡單來說,core mp說的是操作系統執行的一個動作,當某個進程因為一些原因意外終止(crash)的時候,操作系統會將這個進程當時的內存信息轉儲(mp)到磁碟上1。產生的文件就是core文件了,一般會以core.xxx形式命名。 如何產生Core Dump 發生doremp一般都是在進程收到某個信號的時候,linux上現在大概有60多個信號,可以使用 kill -l 命令全部列出來。sagi@sagi-laptop:~$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX針對特定的信號,應用程序可以寫對應的信號處理函數。如果不指定,則採取默認的處理方式, 默認處理是coremp的信號如下:3)SIGQUIT 4)SIGILL 6)SIGABRT 8)SIGFPE 11)SIGSEGV 7)SIGBUS 31)SIGSYS 5)SIGTRAP 24)SIGXCPU 25)SIGXFSZ 29)SIGIOT 我們看到SIGSEGV在其中,一般數組越界或是訪問空指針都會產生這個信號。另外雖然默認是這樣的,但是你也可以寫自己的信號處理函數改變默認行為,更多信號相關可以看參考鏈接33。 上述內容只是產生coremp的必要條件,而非充分條件。要產生core文件還依賴於程序運行的shell,可以通過ulimit -a命令查看,輸出內容大致如下:sagi@sagi-laptop:~$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheling priority (-e) 20 file size (blocks, -f) unlimited pending signals (-i) 16382 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) unlimited virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 看到第一行了吧,core file size,這個值用來限制產生的core文件大小,超過這個值就不會保存了。我這里輸出是0,也就是不會保存core文件,即使產生了,也保存不下來==! 要改變這個設置,可以使用ulimit -c unlimited。 OK, 現在萬事具備,只缺一個能產生Core的程序了,介個對C程序員來說太容易了。#include ; #include ; int crash() { char *xxx = "crash!!"; xxx[1] = 'D'; // 寫只讀存儲區! return 2; } int foo() { return crash(); } int main() { return foo(); } 上手調試 上邊的程序編譯的時候有一點需要注意,需要帶上參數-g, 這樣生成的可執行程序中會帶上足夠的調試信息。編譯運行之後你就應該能看見期待已久的「Segment Fault(core mped)」或是「段錯誤 (核心已轉儲)」之類的字眼了。看看當前目錄下是不是有個core或是core.xxx的文件。祭出linux下經典的調試器GDB,首先帶著core文件載入程序:gdb exefile core,這里需要注意的這個core文件必須是exefile產生的,否則符號表會對不上。載入之後大概是這個樣子的:sagi@sagi-laptop:~$ gdb coremp core Core was generated by ./coremp'. Program terminated with signal 11, Segmentation fault. #0 0x080483a7 in crash () at coremp.c:8 8 xxx[1] = 'D'; (gdb)我們看到已經能直接定位到出core的地方了,在第8行寫了一個只讀的內存區域導致觸發Segment Fault信號。在載入core的時候有個小技巧,如果你事先不知道這個core文件是由哪個程序產生的,你可以先隨便找個代替一下,比如/usr/bin/w就是不錯的選擇。比如我們採用這種方法載入上邊產生的core,gdb會有類似的輸出:sagi@sagi-laptop:~$ gdb /usr/bin/w core Core was generated by ./coremp'. Program terminated with signal 11, Segmentation fault. #0 0x080483a7 in ? () (gdb)可以看到GDB已經提示你了,這個core是由哪個程序產生的。 GDB 常用操作 上邊的程序比較簡單,不需要另外的操作就能直接找到問題所在。現實卻不是這樣的,常常需要進行單步跟蹤,設置斷點之類的操作才能順利定位問題。下邊列出了GDB一些常用的操作。 啟動程序:run
設置斷點:b 行號|函數名
刪除斷點:delete 斷點編號
禁用斷點:disable 斷點編號
啟用斷點:enable 斷點編號
單步跟蹤:next 也可以簡寫 n
單步跟蹤:step 也可以簡寫 s
列印變數:print 變數名字
設置變數:set var=value
查看變數類型:ptype var
順序執行到結束:cont
順序執行到某一行: util lineno列印堆棧信息:bt
『叄』 如何調試php的Core之獲取基本信息
首先, 讓生成一個供舉例子的Core文件: <?phpfunction recurse($num) { recurse(++$num);} recurse(0); 運行這個PHP文件: $ php test.phpSegmentation fault (core mped) 這個PHP因為無線遞歸, 會導致爆棧, 從而造成 segment fault而在PHP的當前工作目錄產生Coremp文件(如果你的系統沒有產生Coremp文件, 那請查詢ulimit的相關設置). 好, 現在, 讓刪除掉這個test.php, 忘掉上面的代碼, 我們現在僅有的是這個Core文件, 任務是, 找出這個Core產生的原因, 以及發生時候的狀態. 首先, 讓用gdb打開這個core文件: $ gdb php -c core.31656 會看到很多的信息, 首先讓我們注意這段: Core was generated by `php test.php'.Program terminated with signal 11, Segmentation fault.
『肆』 怎麼打開core文件
core文件是由應用程序收到系統信號後崩潰產生的,該文件中記錄了程序崩潰的原因(例如收到那種信號),調用堆棧和崩潰時的內存及變數值等等的信息。 打開core文件與編譯時使用的編譯器有關,但絕大多數linux程序是使用gcc編譯器編譯的,因此可使用對應gdb調試器打開,命令格式如下: $ gdb 應用程序文件名 core文件名 舉例: $ gdb /usr/bin/gedit ~/core ------ 查看由gedit崩潰產生的core文件 (gdb) bt ------ 或者backtrace, 查看程序運行到當前位置之前所有的堆棧幀情況) (gdb) quit ------ 退出 如果不知道core文件由哪個文件產生的,可使用file命令顯示 $ file cor