1. 程式人生 > >Linux下使用gdb除錯C/C++程式

Linux下使用gdb除錯C/C++程式

在筆者工作實踐中,使用gdb除錯C++程式和除錯C程式,他們稍有不同,下面是使用總結。
一、編譯選項
-g         生成除錯資訊
-gstabs+   以stabs格式生成除錯資訊,並且包含僅供gdb使用的額外除錯資訊生成除錯資訊,是阻止編譯器將區域性變數優化的暫存器裡,
                  筆者在除錯C++程式時,不加這個選項,所有的變數都打印不出來,gdb提示說沒有這個符號 
二、打斷點 
對於C程式,程式碼都是函式封裝,打斷點很容易,但是C++程式碼都是類封裝,而且函式還可以過載前2種打斷點的方式主要用於C程式,後3種多用於C++程式
1、b funcName 即在函式入口處打斷點
2、b lineNum  在某一行打斷點
3、b className::funcName或者 b className::funcName(type,type) 在某個類的某個函式入口打斷點,由於類的函式有過載,可以在函式名內加上引數型別
4、b fileName:lineNum   在某個原始檔的某一行打斷點
5、b fileName:funcName  在某個原始檔的某個函式入口打斷點
三、常用命令

1、finish           一直執行到當前函式返回,即跳出當前函式
2、r                   執行程式(run)
3、n                  執行下一條語句(next 不會進入函式內部)
4、s                  執行下一條語句(step 會進入函式內部)
5、回車鍵        重複執行上一條命令
6、c                  繼續執行直到下一個斷點(continue)
7、p                 列印變數的值(print)
8、bt                檢視函式堆疊(backtrce)
9、q                 退出gdb除錯(quit)
10、info break       檢視斷點資訊
11、delete breakNum  刪除某個斷點
四、bt命令除錯段錯誤

在Linux下程式設計,一不下心就會出現段錯誤(Segmentation fault),關於段錯誤的產生,筆者目前只是大概知道是記憶體的非法訪問造成的,比如訪問空指標,指標越界訪問都會造成段錯誤,關於本質原因,還需要研究Linux記憶體管理、程序空間等知識,這方面有待後續深入研究。下面演示如何利用 core檔案定位程式段錯誤。

測試程式碼:segfault.c

/*************************************************************************
    > File Name: segfault.c
    > Author: KentZhang
    > Mail: 
[email protected]
> Created Time: Thu 27 Aug 2015 02:48:37 PM CST ************************************************************************/ #include<stdio.h> void test_seg_fault() { printf("test_seg_fault() start.\n"); char *p=NULL; *p = 'a'; printf("test_seg_fault() end.\n"); } void main() { test_seg_fault(); }

1、 編譯程式生成可執行檔案

gcc -g segfault.c -o segfault  

2、生成Core檔案

執行命令:ulimit  -c  unlimited

執行程式:./segfault

     [[email protected] MyDir]# ls
             core.8450  segfault  segfault.c

3、啟動gdb,列印棧資訊

執行命令:gdb  ./segfault  ./core.8450

然後執行:bt

Loaded symbols for /lib64/ld-linux-x86-64.so.2

Core was generated by `./segfault'.
Program terminated with signal 11, Segmentation fault.
#0  0x00000000004004e2 in test_seg_fault () at segfault.c:13
13 *p = 'a';
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.x86_64
(gdb) bt
#0  0x00000000004004e2 in test_seg_fault () at segfault.c:13
#1  0x00000000004004ff in main () at segfault.c:19
(gdb) 

4、分析結果

              本例項中,程式崩潰後,保留了2層棧的資訊,#0 棧,是程式發生崩潰時所在的棧,即是在test_seg_fault函式內發生崩潰,在segfault.c檔案的第13行,這一句發生段錯誤,到此定位完成。其實函式每呼叫一層,就會有一層棧的資訊,最上面的總是 #0 號棧,即程式當前所在的棧,這很符合壓棧操作。

由於筆者的水平有限,出錯在所難免,懇請讀者拍磚指正,謝謝閱讀