一.引言
在日常程序開發中不免遇到類似空指針操作導致程序崩潰的問題,所以需要一定的手段去定位bug,而斷點調試是普遍使用的技巧,比如Windows中用VC++的debug模式進單步運行、斷點調試等,而且是圖形化操作界面很友好,但在Linux系統中使用的是沒有圖形界面的調試工具-GDB(聽說eclipse支持GUI調試,暫未嘗試),所以需要通過指令進行操作,下面逐步介紹gdb調試環境的搭建和使用方法。
二.gdb調試環境搭建
(1)下載gdb工具源碼:http://www.gnu.org/software/gdb/download/
選擇下載最新版本:
注:由於個人本地arm-linux-gcc版本較低(4.4.3)不支持 C++11,后面下載編譯的是 gdb-7.12
(2)解壓
解壓tar.gz文件:tar -zxvf xxx.tar.gz
解壓tar.xz文件:先 xz -d xxx.tar.xz 將 xxx.tar.xz解壓成 xxx.tar 然后,再用 tar xvf xxx.tar來解包。
(3)編譯安裝
--------①編譯gdb(在Linux主機上運行的工具)
./configure --target=arm-linux //配置要調試的目標為arm-Linux開發板(前提已經配置了arm-linux-gcc交叉編譯環境) make make install //默認安裝路徑可以在Makefile中看到:prefix = /usr/local
也可以指定安裝目錄,比如 : make install prefix=$PWD/tmp
環境變量添加該路徑 或 復制arm-linux-gdb到/bin目錄下后便可作為系統工具使用。
錯誤1:
location.c:527:19: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
|| *argp == '\0'
解決方法: || *argp == '\0' 修改為 || *argp == NULL
錯誤2:
make[5]: 進入目錄“/home/sheldon/work/linux_project/gdb-8.2/gdb/doc” /home/sheldon/work/linux_project/gdb-8.2/missing makeinfo --split-size=5000000 --split-size=5000000 -I ./../../readline/doc -I ./../mi -I . \ -o gdb.info ./gdb.texinfo /home/sheldon/work/linux_project/gdb-8.2/missing: 81: /home/sheldon/work/linux_project/gdb-8.2/missing: makeinfo: not found WARNING: 'makeinfo' is missing on your system. You should only need it if you modified a '.texi' file, or any other file indirectly affecting the aspect of the manual. You might want to install the Texinfo package: <http://www.gnu.org/software/texinfo/> The spurious makeinfo call might also be the consequence of using a buggy 'make' (AIX, DU, IRIX), in which case you might want to install GNU make: <http://www.gnu.org/software/make/> make[5]: *** [gdb.info] 錯誤 127 make[5]: 離開目錄“/home/sheldon/work/linux_project/gdb-8.2/gdb/doc” make[4]: *** [subdir_do] 錯誤 1 make[4]: 離開目錄“/home/sheldon/work/linux_project/gdb-8.2/gdb” make[3]: *** [install-only] 錯誤 2 make[3]: 離開目錄“/home/sheldon/work/linux_project/gdb-8.2/gdb” make[2]: *** [install] 錯誤 2 make[2]: 離開目錄“/home/sheldon/work/linux_project/gdb-8.2/gdb” make[1]: *** [install-gdb] 錯誤 2 make[1]: 離開目錄“/home/sheldon/work/linux_project/gdb-8.2” make: *** [install] 錯誤 2 sheldon@sheldon-vm:~/work/linux_pro
解決方法:sudo apt-get install texinfo (或者從GNU下載源碼自行編譯安裝:http://ftp.gnu.org/gnu/texinfo/)
--------②編譯gdbserver(在Linux開發板上作為父進程運行,啟動加了gdb調試信息的應用程序)
cd gdb/gdbserver/ //繼續進入到gdbserver目錄 ./configure --host=arm-linux //配置要運行的平台為arm-Linux開發板 make
make install prefix=../../tmp/gdbserver //指定安裝到之前的tmp目錄下
將編譯生成的gdbserver通過nfs或usb復制到開發板上,后面就可以開始遠程gdb調試了!
三.調試方法
(1)編寫測試程序:
#include <stdio.h> void C(int *p) { *p = 0x12; } void B(int *p) { C(p); } void A(int *p) { B(p); } void A2(int *p) { C(p); } int main(int argc, char **argv) { int a; int *p = NULL; A2(&a); // A2 > C printf("a = 0x%x\n", a); A(p); // A > B > C 故意操作空指針 return 0; }
編譯生成可執行文件(-g選項增加gdb調試信息):
arm-linux-gcc test_debug.c -g -o test_debug
(2)發現在ARM板上運行test_debug后產生段錯誤,接下來就啟動gdbserver來定位問題:
gdbserver 192.168.1.17:2345 ./test_debug //開發板通過gdbserver執行test_debug,並開啟網絡端口監聽
(3)在PC上執行
/bin/arm-linux-gdb ./test_debug //讀取應用程序 target remote 192.168.1.17:2345 //通過開發板監聽的網絡端口傳輸控制指令
然后便可使用gdb命令來遠程控制程序運行進行調試:
示例①:main函數入口打個斷點,然后繼續運行:
示例②:在代碼的31行處打斷點,然后繼續運行:
示例③:進入函數A2執行C(p),然后繼續進入函數C到*p = 0x12(此時該語句還未執行),打印*p的隨機值為33620,再繼續執行賦值操作后打印值為賦值的0x12即十進制18:
更詳細的使用方法可參考如下指令自行調試:
命令 |
命令縮寫 |
命令說明 |
list |
l |
顯示多行源代碼 |
break |
b |
設置斷點,程序運行到斷點的位置會停下來 |
info |
i |
描述程序的狀態 |
run |
r |
開始運行程序 |
display |
disp |
跟蹤查看某個變量,每次停下來都顯示它的值 |
step |
s |
執行下一條語句,如果該語句為函數調用,則進入函數執行其中的第一條語句 |
next |
n |
執行下一條語句,如果該語句為函數調用,不會進入函數內部執行(即不會一步步地調試函數內部語句) |
|
p |
打印內部變量值 |
continue |
c |
繼續程序的運行,直到遇到下一個斷點 |
set var name=v |
|
設置變量的值 |
start |
st |
開始執行程序,在main函數的第一條語句前面停下來 |
file |
|
裝入需要調試的程序 |
kill |
k |
終止正在調試的程序 |
watch |
|
監視變量值的變化 |
backtrace |
bt |
產看函數調用信息(堆棧) |
frame |
f |
查看棧幀 |
quit |
q |
退出GDB環境 |
后面運行到操縱空指針處便打印了相關異常信息,這樣就能大致定位出具體哪條語句處出現問題:
四.另一種調試方法(非單步調試):
讓程序在開發板上直接運行,當它發生錯誤時,令它產生core dump文件,然后使用gdb根據core dump文件找到發生錯誤的地方,具體步驟如下:
(1)在ARM板上進行如下操縱:
ulimit -c unlimited //一般Linux系統不會產生core dump文件(默認大小0),所以需要對core文件重新設置大小 ./test_debug //程序出錯時會在當前目錄下生成名為core的文件
如下就是產生了core文件:
(2)將core文件復制到PC上進行如下操縱:
/bin/arm-linux-gdb ./test_debug ./core
執行后便可看到程序終止的信息並提示了具體出錯位置:
另外也可以通過 bt 指令打印函數調用信息(堆棧) main->A->B->C,然后到第6行異常終止:
以上便是gdb調試的一般方法,更靈活的操作技巧需要多參考相關資料加以實踐~
-end-