在公司工作了一段時間,發現
b/s結構的**除錯很麻煩,經常用的手段是通過
printf
打一串訊息來進行跟蹤,然後估計問題出在**。通過逐步新增
printf
語句,獲得越來越多的資訊最終確定問題的根源。我感覺這樣比較麻煩,如果能把
gdb的單步除錯功能用上就好了。工作之餘,做了一定的嘗試,希望對跟我一樣感到麻煩的人有一丁點幫助。
除錯資訊的生成
進行gdb
除錯時最重要的是要儲存除錯資訊,.c與
.cpp
檔案編譯之後可生成.o、
.a、.so以及可執行檔案等等。如果依賴檔案中存在.c或
.cpp
檔案,編譯時加上
-g選項,那麼就可以用
gdb除錯目標檔案了。值得注意的是:如果將.c或
.cpp
編譯(加上了
-g)成
.o檔案,再將這些
.o檔案編譯(沒有用到
-g)成
.so,雖然編譯成
.so時沒有用到
-g,但
.so檔案中仍然儲存了除錯資訊,仍可用
gdb除錯。
儲存除錯資訊的根源在於用
-g編譯.c與
.cpp
檔案,其他中間過程可不用-g。
利用部分原始檔除錯
gdb除錯時,如果有源**,那就能單步執行,一步一步的檢視結果,能方便的定位問題。但是,如果源**很龐大,而公司又不允許把全部**拿出去除錯,那就可以只拿一部分**出去除錯。在此我做了乙個小實驗來說明這個問題。
假設**放在
3個目錄下:
1. show
目錄,包含
2個檔案:【1
】show.h
void show();【2
】show.c
#include "show.h"
#include
void show()
2. display
目錄,包含
2個檔案:【1
】display.h
void display()【2
】display.c
#include "display.h"
#include
void display()
3.main
目錄,包含乙個檔案:
#include "../show/show.h"
#include "../display/display.h"
int main()
將show.c
編譯成共享庫:
gcc -shared -g -o libshow.so show.c
,將libshow.so
拷貝到/lib下。將
display.c
編譯為.o
檔案:gcc -g -c display.c
。生成可執行檔案:
gcc -g -o main main.c ../display/display.o –lshow
。此時可用
gdb main
進行單步除錯,執行到
show();時按s
進入函式。如果將
.so與
main
拷貝到另一台機器上,不拷貝原始碼,執行
gdb main
時由於沒有原始碼,無法單步除錯,此時將
main.c
拷貝過來即可單步除錯。
如果想進入
show
函式除錯,可將
show.c
拷貝過來,放到跟
main
同樣的路徑下。
同理,如果想進入
display
函式除錯,可將
display.c
拷貝過來,放到跟
main
同樣的路徑下。
無論編譯時原始檔的路徑怎樣,部署之後,只需將原始檔與可執行檔案放在同一目錄即可進行除錯。
另外乙個問題是,如果沒有拷貝
main.c
,又想除錯
display
函式怎麼辦?這就需要用到斷點:【1
】gdb main 【
2】l display.c:1 【
3】b display.c:6 【
4】r
可以看到已經執行到
display
函式裡邊了,這下又可以通過按
n來進行單步除錯了。同樣的方法適用於除錯
show
函式,不過用「
l show.c:1
」時會提示找不到原始檔(這一步可不必執行),此時不用理會直接用「
b show.c:6
」設定斷點即可。
段錯誤的處理
程式執行時經常遇到煩人的段錯誤,可用
core
檔案進行除錯。
敲入指令「
ulimit -c
」,如果輸出
0就表示不會產生
core
檔案,應該進行修改以允許
core
檔案的產生,「
ulimit -c unlimited
」或者「
ulimit -c 1024
」等等。
假設執行
main
時產生了段錯誤並產生了
core
檔案「core.2182
」,此時就可以用「
gdb main core.2182
」進行除錯,就可以看到出錯資訊,如果有原始檔並且編譯時用到了
-g,那就還可以看到出錯的是哪條語句。
總的來說,編譯.c或
.cpp
時加上-g
選項儲存除錯資訊,可將我們關注的部分源**與可執行檔案放在同一目錄下進行單步除錯跟蹤,當程式出現段錯誤時可利用
core
檔案檢視出錯資訊。
GDB除錯技巧
談到gdb,不能不對他的強大功能所折服,在我所用過的所有偵錯程式中,這實在是乙個強大的除錯工具,今天就說說gdb的簡單用法。gdb是gnu開源組織發布的乙個強大的unix下的程式除錯工具。或許,各位比較喜歡那種圖形介面方式的,像vc bcb等ide的除錯,但如果你是在 unix平台下做軟體,你會發現...
gdb除錯技巧
1 以結構體形式訪問某個記憶體 print type addr 其中type是結構體型別,addr是記憶體的位址 2 顯示符號表 info symbol info symbol symbol addr symbol addr為對應的位址 print 符號名 3 檢視型別的原型定義 有時候在除錯大型程...
gdb除錯技巧
1 按結構體格式列印 set print pretty on 2.檢測點 watch 為表示式 變數 expr設定乙個觀察點。一量表示式值有變化時,馬上停住程式。rwatch 當表示式 變數 expr被讀時,停住程式。awatch 當表示式 變數 的值被讀或被寫時,停住程式。info watchpo...