程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Linux環境下的C/C++基礎調試技術3——查看數據

Linux環境下的C/C++基礎調試技術3——查看數據

編輯:C++入門知識

本文首先以一個二叉樹插入算法的實現作為例子說明GDB查看程序數據的相關方法,代碼如下:

  1: //  bintree.c:  routines to do insert and sorted print of a binary tree

  2:

  3: #include

  4: #include

  5:

  6: struct node {

  7:    int val;             // stored value

  8:    struct node *left;   // ptr to smaller child

  9:    struct node *right;  // ptr to larger child

 10: };

 11:

 12: typedef struct node *nsp;

 13:

 14: nsp root;

 15:

 16: nsp makenode(int x)

 17: {

 18:    nsp tmp; 

 19:

 20:    tmp = (nsp) malloc(sizeof(struct node)); 

 21:    tmp->val = x; 

 22:    tmp->left = tmp->right = 0;

 23:    return tmp;

 24: }

 25:

 26: void insert(nsp *btp, int x)

 27: {

 28:    nsp tmp = *btp;

 29:

 30:    if (*btp == 0) {

 31:       *btp = makenode(x);

 32:       return;

 33:    }

 34:

 35:    while (1)

 36:    {

 37:       if (x < tmp->val) {

 38:

 39:          if (tmp->left != 0) {

 40:             tmp = tmp->left;

 41:          } else {

 42:             tmp->left = makenode(x);

 43:             break;

 44:          }

 45:

 46:       } else {

 47:

 48:          if (tmp->right != 0) {

 49:             tmp = tmp->right;

 50:          } else {

 51:             tmp->right = makenode(x);

 52:             break;

 53:          }

 54:

 55:       }

 56:    }

 57: }

 58:

 59:

 60: void printtree(nsp bt)

 61: {

 62:    if (bt == 0) return;

 63:    printtree(bt->left);

 64:    printf("%d ",bt->val);

 65:    printtree(bt->right);

 66: }

 67:

 68:

 69: int main(int argc, char *argv[])

 70: {

 71:    root = 0;

 72:    for (int i = 1; i < argc; i++)

 73:       insert(&root, atoi(argv[i]));

 74:    printtree(root);

 75: }
在調試這個二叉樹插入程序的時候,我們會非常關心insert方法的執行情況,在進入那個while(1)循環後,我們可能會做以下的操作:

(gdb) p tmp->val
$1=12
(gdb) p tmp->left
$2 = (struct node *) 0x8049698
(gdb) p tmp->right
$3 = (struct node *) 0x0

這個操作顯得累贅又麻煩,我們可以有以下的改進措施:

1.直接打印結構體tmp:

(gdb) p *tmp
$4 = {val = 12, left = 0x8049698, right = 0x0}

2.使用display命令:我們在#37設置斷點,然後運行程序,待程序運行至該斷點停下後使用display = disp 命令對某一個變量進行監視(之所以這樣做是因為這個變量必須存在在該棧幀上,也就是說調試的時候這個變量的確被創建並且沒有被銷毀),程序以後只要一停止就打印這個變量的值在屏幕上:

(gdb) disp *tmp
1: *tmp = {val = 12, left = 0x8049698, right = 0x0}
(gdb) c
Continuing.
Breakpoint 1, insert (btp=0x804967c, x=5) at bintree.c:37
37 if (x < tmp->val) {
1: *tmp = {val = 8, left = 0x0, right = 0x0}

也可以使用dis disp 1使這個監視動作失效(enable disp 1則恢復),undisp 1為刪除。info display為查看當前所有自動打印點相關的信息

3.使用命令列表:在上篇中已經敘述,在此不再贅述。

4.使用call命令:我們在代碼中已經有了一個打印整個樹的函數printtree,使用call命令我們可以直接利用代碼中的方法進行變量監視,在每次insert完成的時候調用printtree對二叉樹進行打印:

(gdb) commands 2
Type commands for when breakpoint 2 is hit, one per line.
End with a line saying just "end".
>printf "*********** current tree ***********"
>call printtree(root)
>end

5.使用DDD的Data Window圖形化表示:單擊右鍵在root這個變量上然後選擇display *root,每次在#37行停下時,在Data Window內對整個樹的都有圖形化表示,在左右子樹上,你可以使用右鍵單擊然後選擇Display *()來顯示。(Tips:你可以以--separate參數啟動DDD,這樣每個Window都是獨立的,你可以獲得更大的視野)。

補充:

1.打印數組:p *pointer@number_of_elements,其中number_of_elements表示顯示pointer這個變量中的幾個成員。另外一種方式是類型轉換,例如下列程序:

  1: int *x;

  2: main()

  3: {

  4:    x = (int *) malloc(25*sizeof(int));

  5:    x[3] = 12;

  6: }
除了可以使用:

(gdb) p *x@25
$1 = {0, 0, 0, 12, 0 }

我們還可以使用:

(gdb) p (int [25]) *x
$2 = {0, 0, 0, 12, 0 }

2.打印本地變量:info locals,會打印當前棧幀的本地變量。

3.以不同形式打印變量:p/paramenters variable  parameters 可以是 x 表示打印變量以十六進制表示,f為浮點,c為character,s為string。

4.打印歷史查看過的變量:使用$number,而只使用$表示上一個變量。

(gdb) p tmp->left
$1 = (struct node *) 0x80496a8
(gdb) p *(tmp->left)
$2 = {val = 5, left = 0x0, right = 0x0}
(gdb) p *$1
$3 = {val = 5, left = 0x0, right = 0x0}

(gdb) p tmp->left
$1 = (struct node *) 0x80496a8
(gdb) p *$
$2 = {val = 5, left = 0x0, right = 0x0}

5.修改被調試程序運行時的變量值:set x = 12。

6.利用自定義變量方便調試:例如,

  1: int w[4] = {12,5,8,29};

  2: main()

  3: {

  4:    w[2] = 88;

  5: }
我們設置i,然後利用這個變量對這個數組進行遍歷:

(gdb) set $i = 0
(gdb) p w[$i++]
$1=12
(gdb)
$2=5
(gdb)
$3=88
(gdb)
$4=29

7.強制類型打印

p {type}address:把address指定的內存解釋為type類型(類似於強制轉型,更加強)

8.設置一些常見選項

1) set print array:打開數組顯示,打開後當數組顯示時,每個元素占一行,如果不打開的話,每個元素則以逗號分隔。默認關閉
2) set print elements num-of-elements:設置GDB打印數據時顯示元素的個數,缺省為200,設為0表示不限制(unlimited)
3) set print null-stop:設置GDB打印字符數組的時候,遇到NULL時停止,缺省是關閉的
4) set print pretty:設置GDB打印結構的時候,每行一個成員,並且有相應的縮進,缺省是關閉的
5) set print object:設置GDB打印多態類型的時候,打印實際的類型,缺省為關閉 <

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved