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

Linux環境下的C/C++基礎調試技術1——初步了解(2010.12.5更新)

編輯:C++入門知識

Author:gnuhpc
WebSite:blog.csdn.net/gnuhpc

1.調試技術的幾個准則

  • 驚喜准則:找到錯誤是一種驚喜,心理上不要畏懼而是要懷著感恩的心去面對。
  • 從小處開始准則:剛開始測試的使用從小處著手,暫時不涉及邊界數據,雖然這樣可能會掩蓋一些Bug,但是這樣或許能查到最主要的Bug,例如你的程序包含了一個巨大的循環體,最容易發現的Bug在第一個循環或第二次循環執行的時候。
  • 自頂向下准則:優先選擇step over而不是step into,以節省時間。
  • Segmentation Fault准則:出現段錯誤時,第一個想到的不應該是printf而是Debugger,因為在調試器中你能看到你的哪一行代碼導致了錯誤,更重要的是你可以通過backtrace等工具得到更多有用的信息。
  • 折半查找准則:在尋找bug時可以充分利用編輯器等工具來進行折半查找,具體在後邊有例子說明。

2.Linux下代碼調試工具

主要使用的GDB,以及基於GDB的圖形化工具,如DDD或eclipse,選擇上看個人習慣了。

命令行式的GDB啟動較快,可以在ssh終端下使用,操作簡潔,並且在調試GUI程序時不會崩潰,但較之圖形化則在單步調試或設置斷點時非常不方便。

當然你可以使用Vim等編輯器的插件或者補丁(clewn or vimGDB)來彌補這一缺憾,並且在GDB6.1以上的版本你可以使用GDB -tui這個模式(或者在GDB的命令行模式下按CTRL-x-a)打開一個類似於圖形界面的文本界面模式,在這個界面中你可以使用上下鍵查看源代碼(CTRL-P 和 CTRL-N完成輸入過的命令的查看).

或者你還可以使用cGDB這個工具(很慶幸這個項目在停止了三年後又有人開始維護了),這個工具是將GDB用curses包裝了一下,提供了一些很好用的feature(Esc和i鍵在代碼和命令框間切換;在代碼框中支持vim型的操作;在命令框中支持tab鍵補全命令;在移動到想加入斷點的行(行號為高亮白色)直接用空格鍵,設定好後行號會變紅;)。另外,在調試C-S程序時推薦使用eclipse。

在本文中,重點介紹ddd的操作,因為這個工具即結合了GDB命令行和圖形界面的操作。其余請參閱各個工具的手冊。

3.GDB命令行最基本操作

  • 設置斷點:b LineNumber
  • 運行程序:r args1 args2 ...
  • 徹底終止程序:kill
  • 單步執行:n(TIPs1:可以按回車重復上一次操作,在單步調試時這個feature很有用)。
  • 單步進入:s
  • 繼續執行:c
  • 設置臨時斷點:tb LineNumber 可以理解為一次性斷點,與斷點不同,臨時斷點只在第一次執行時起作用。
  • 查看變量:p
  • 設置觀察點:
    • w Expression,當Expression是一個變量名時,這個變量變化時會停止執行;你也可以使用條件來限定,比如w (z>28),當z大於28時,程序停止。注意觀察點一般使用在更大范圍上的變量,而不是本地變量,因為在局部變量上設置的觀察點在局部結束時(比如該變量所在的函數執行結束時)就被取消了。
    • 當然這並不包含main的情況,因為main函數執行結束後程序就結束了。
  • 查看棧幀:
    • 棧幀指的是在一個函數調用時,該函數調用的運行信息(包含本地變量、參數以及函數被調用的位置)存儲的地方。每當一個函數被調用時,一個新的幀就被系統壓入一個由系統維護的幀,在這個棧的頂端是現在正在運行的函數信息,當該函數調用結束時被彈出並析構。
    • 在GDB中,frame 0為當前幀,frame 1為當前幀的父幀,frame 2為父幀的父幀,等等,用down命令則是反向的。這是一個很有用的信息,因為在早期的一些幀中的信息可能會給你一些提示。
    • backtrace查看整個幀棧
    • 注意:在幀中來回並不影響程序的執行。

實例:插入排序算法調試

用偽代碼描述這個過程如下:

image

擬調試代碼如下:

//
// insertion sort, 
//
// usage:  insert_sort num1 num2 num3 ..., where the numi are the numbers to
// be sorted
int x[10],  // input array
    y[10],  // workspace array  
    num_inputs,  // length of input array
    num_y = 0;  // current number of elements in y
void get_args(int ac, char **av)
{  int i;
   num_inputs = ac - 1;
   for (i = 0; i < num_inputs; i++)
      x[i] = atoi(av[i+1]);
}
void scoot_over(int jj)
{  int k;
   for (k = num_y-1; k > jj; k++)
      y[k] = y[k-1];
}

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