斯坦佛編程教程-Unix編程工具(三)

來源:互聯網
上載者:User

你的程式中可能存在一兩個bug,有很多找bug的方法,但是一個好的調試器可以讓這個工作變得簡單起來。在大部分的各種大小的程式中,找出程式中所有的bug幾乎是不可能的,你只能一直盯著代碼——你需要通過程式運行時的行為來找出這個bug。投資一些時間來好好學習一下調試器非常值得的。

GDB
我們把GNU的調試器稱作gdb,它幾乎在每一個領域都超過了dbx,並且和gcc編譯器配合得非常完美。其他的一些漂亮的調試環境包括ups和CodeCenter,但是他們都不如gdb通用,而且CodeCenter可不便宜。雖然gdb沒有一個像其他軟體一樣漂亮的圖形介面,但它能為高端的程式員提供幾乎所有他們想知道的資訊。

這個部分並不會深入描述gdb的每一個細節,但是重要的部分我們都會提到。我們可以用help命令來查看gdb線上的協助。如果你需要更多的資訊,試著在終端用xinfo命令來擷取,或者使用emacs的info-browser模式。

開始調試
在make的時候有兩種方式來調用gdb,要在shell中啟動調試器,只要在終端輸入:
gdb program

program是你要進行調試的目標可執行檔。如果你在調用gdb的時候沒有指明任何目標的話,gdb在啟動後會讓你指定目標檔案,然後你才能做一些有用的事。

另一種選擇是在使用emacs的時候你可以用[Esc]-x 調用gdb,之後會提示你可執行檔的名字。如果emacs沒有指明目標,則你無法使用gdb。emacs的視窗會分裂成兩個部分,一個顯示gdb的資訊,另一個顯示源檔案。

運行調試器
當你開始啟動並執行時候,調試器會裝載你的程式和它的特徵表(包含了一些比如變數名,源檔案等等的有用資訊)。這個特徵表就是-g這個編譯條件所產生的,調試器會讀取這些資訊來運行程式。

調試器是一個互動性的程式,當它啟動的時候,它會給你提示框用來輸入命令,調試器中最常用的命令有:設定斷點,單步調試,斷點後繼續運行,檢查變數的值.

運行程式
run 重設程式,從最開始的地方開始運行。你可以在啟動並執行時候提供一些參數,方式如同你在終端運行程式是一樣的。
step 單步跟蹤調用,運行源檔案的下一行代碼,並返回調試器。如果調用了子程式,那麼就跟蹤到子程式。
step count 運行到原始碼的"count"行。
next  單步調用,不會跟蹤到子程式。
finish 一直運行到當前方法或函數完成。
return 將選取的棧的幀返回到它的調用者處。
jump address 從某個地方或某一行繼續運行程式

當一個目標可執行檔第一次被選中,那麼當前的源檔案就是main函數所在的檔案,而當前的程式碼就是方法裡面的第一行執行的代碼。
當你在運行程式的時候,總會運行到一些源檔案的某一行,當你暫停程式的時候(當程式流遇到斷點的時候),當前的目標檔案就是當前執行代碼所在的源檔案。同樣的,當前原始碼行就是你所執行的程式碼。

斷點
你可以在程式中的某一行設定斷點。每一個斷點在設定的時候都會被加上一個編號,然後你就可以通過編號來操縱它了。
你可以用break命令在代碼中你想讓程式停下來的地方來設定斷點,斷點的位置可以通過很多的方式來設定,比如用檔案名稱或是行號或是方法名(行中要有實際啟動並執行代碼——注釋和空格都不能算)。如果檔案沒有指定,那麼就預設為當前的目標檔案,如果沒有設定斷點,那麼當前程式碼就是斷點。
gdb提供了以下一些命令來控制斷點:
info break 列印初所有的斷點的位置和狀態。
break function 在指定的方法的開始的位置設定一個斷點。
break linenumber 在當前源檔案特定的行設定一個斷點。
break filename:linenumber 在特定檔案的特定行設定一個斷點。
你也可以設定一個if語句來建立一個條件斷點:
break fn if expression 當運算式的值為正的時候就在斷點處停止。運算式可以是任何C的運算式,當遇到斷點的時間偶就會使用當前的棧來計算。
disable/enable breaknum 在設定了斷點的行開/關斷點。
delete breaknum 刪除某行的斷點
commands breaknum 設定當程式運行到斷點處時將要啟動並執行命令。命令可以是任意的C聲明或是gbd命令。這可以用於即時的編碼而不用重新編譯(太棒了!)。
cont 繼續運行已停止的程式。

例如,下面的命令...
break binky.c:120
break DoGoofyStuff

在binky.c的120行處設定斷點,而另一個斷點在方法DoGoofyStuff這個方法的首行。當程式運行到這些位置的時候,程式將會停止讓你在調試器中擷取一些資訊。
Gdb和其他大部分的調試器都提供了決定程式運行方式的機制。我們經常會問到我運行到了程式的哪個位置(a)還有程式中的變數的值是多少(b)。

檢查棧
為了回答問題(a),我們可以用breaktrace命令來檢查程式運行棧。程式運行棧類似於程式運行時留下的腳印;每當方法被調用的時候,運行棧就會被建立,當方法運行到return的時候,運行棧就會清空,然後棧也會被回收。這些棧幀包含著一系列調用語句的變數資訊還有每個方法調用所傳遞的參數。方法調用語句會將當前運行跳轉到相應的方法中去。

Gdb將棧幀設定成從0到無窮大的有序幀。任何時候,gdb都是只將一個幀作為當前幀。對於選定的幀,變數的尋找是確定的。當程式的在調試遇到斷點的時候,gdb會選擇最內層的幀。下面的一些命令可以用於通過序號或是地址來選擇其他的幀。
backtrace 顯示所有棧幀,在尋找引起程式崩潰的調用序列的時候非常有用。
frame framenumber 檢查幀號為framenummber幀。這個操作並不會改變啟動並執行上下文,但是可以允許不同幀裡的變數。
down 選擇並列印出被調用的棧幀。
up 選擇並列印出調用了這個方法的棧幀。
info args 顯示當前棧幀的參數變數。
info locals 顯示當先幀棧的局部變數。

檢查源檔案
另一個尋找當前程式的運行位置的方法或是尋找其他的有用資訊的方法就是檢查相應的源檔案。gdb提供了下面的幾個命名:

list linenum 列印源檔案中以linenum為中心的10行代碼

list function   列印方法開始附近的10行代碼。

list    列印下面10行代碼。

    list命令會列印出源檔案中以當前行為中心的程式碼,如果在emacs中使用gdb的這些命令就太老土了。


檢查資料

如果要回答“這些變數的值事什嗎?”,那麼你應該使用下面的命令...

print expression    列印運算式的值,運算式是一個有效c運算式,能夠包括方法調用和算數運算式,以及當前棧幀的所有的變數。

set variable=expression    將變數的值設定成運算式所表示的值。你可以設定當前範圍內的所有的變數的值。所有以$開頭的變數都可以用作gdb的臨時變數。

display expression    在程式運行到停止的時候列印運算式的值,在你一步步運行程式的時候,如果你想查看變數的值,這些會非常有用。

undisplay    取消之前的display命令請求。


    在gdb中,有兩種方式來顯示變數的值:顯示一次當前變數的值或是持續顯示變數整個生命週期的值。print命令將會列印當前變數的值,而display命令將會讓調試器在程式啟動並執行每一步都列印變數的值,只要變數還存在。目標值是用c文法來區分的,例如...

print x.y[3]

將會列印x結構體中名為y的數組的第四個變數值。那些可以訪問的變數存在於當前方法的活動幀,還有全域變數和靜態變數。print和display都可以用來列印任意的複雜運算式,甚至是那些包含有方法調用的運算式。但是如有一個方法有副作用,那麼你可得注意了。



縮寫

最後,我們可以更簡單的去使用gdb,那就是所有的命令都可以用縮寫,這樣你就不必每次都打全命令了。一個命令的縮寫就是在不引起歧義的情況下用盡量少的字母來替代命令,一些特殊的命令break,delete,run,continue,step,next,print,你在使用的時候就只需要用首字母就行了。另外,你最後輸入的命令只要按一下return鍵就又可以出現了。這在單步調試的時候查看變數的值將會非常的有用。

更多的命令
editmode mode 設定gdb的命令列模式。mode的值可以是emacs, vi, dumb.
shell command  像在終端運行程式一樣運行完剩下的程式。
history 列印出使用過的命令曆史。

調試策略
一些人因為他們不想去學習另外的工具而不去使用調試器,這是錯誤的!花上一些時間來學習使用一個調試器和他的特性,這將讓你在排除困難的時候更有效率。

很多時候bug會導致程式的崩潰(或者是“核心崩潰”,“註冊機崩潰”等等。),然後你的程式就掛在那,只留下如“片中斷”之類的提示。如果你的程式也會這樣崩潰,那麼調試器就可已截獲到程式的訊號,這些訊號包含著它所發現的錯誤,並且允許你檢查程式的狀態。這樣你花不了多大的力氣,調試器就能顯示出程式在崩潰的時候的狀態。

通常情況下,bug不會引起程式很明顯的崩潰,而是產生一些內部出問題的徵兆。在這種情況下,一種技術就是在程式運行不正常的地方設定一個斷點,然後通過觀察堆棧調用的情況來獲得一些資料,然後控製程序到壞的狀態裡。另一種技術就是在問題開始之前設定一些斷電,然後一步步接近問題,時刻檢查程式啟動並執行狀態。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.