1. 程式人生 > >軟體除錯是雞肋?你的認知決定你的層次!

軟體除錯是雞肋?你的認知決定你的層次!

1955年,一家名為Computer Usage Corporation(CUC)的公司誕生了,它是世界上第一家專門從事軟體開發和服務的公司。CUC公司的創始人是Elmer Kubie和John W. Sheldon,他們都在IBM工作過。他們從當時計算機硬體的迅速發展中看到了軟體方面所潛在的機遇。CUC的誕生標誌著一個新興的產業正式起步了。

與其他產業相比,軟體產業的發展速度是驚人的。短短60餘年後,我們已經難以統計世界上共有多少家軟體公司,只知道這一定是一個很龐大的數字,而且這個數字還在不斷增大。與此同時,軟體產品的數量也達到了難以統計的程度,各種各樣的軟體已經滲透到人類生產和生活的各個領域,越來越多的人開始依賴軟體工作和生活。

與傳統的產品相比,軟體產品具有根本的不同,其生產過程也有著根本的差異。在開發軟體的整個過程中,存在非常多的不確定性因素。在一個軟體真正完成之前,它的完成日期是很難預計的。很多軟體專案都經歷了多次的延期,還有很多中途夭折了。

直到今天,人們還沒有找到一種有效的方法來控制軟體的生產過程。導致軟體生產難以控制的根本原因是源自軟體本身的複雜性。一個軟體的規模越大,它的複雜度也越高。

簡單來說,軟體是程式和文件的集合,程式的核心內容便是按一定順序排列的一系列指令。如果把每個指令看作一塊積木,那麼軟體開發就是使用這些積木修建一個讓CPU(中央處理器)在其中執行的交通系統。這個系統中有很多條不同特徵的道路(函式)。

如果說軟體的執行過程就像是CPU在無數條道路(指令流)間飛奔,那麼開發軟體的過程就是設計和構建這個交通網路的過程。

其基本目標是要讓CPU在這個網路中奔跑時可以完成需求中所定義的功能。對這個網路的其他要求通常還有可靠、靈活、健壯和易於維護,開發者通過簡單的改造就能讓其他型別的車輛(CPU)在上面行駛……

開發一個滿足以上要求的軟體系統不是一件簡單的事,通常需要經歷分析、設計、編碼和測試等多個環節。通過測試併發布後,還需要維護和支援工作。在以上環節中,每一步都可能遇到這樣那樣的技術難題。

在軟體世界中,螺絲刀、萬用表等傳統的探測工具和修理工具都不再適用了,取而代之的是以偵錯程式為核心的各種軟體除錯工具。軟體除錯的基本手段有斷點、單步執行、棧回溯等,其初衷就是跟蹤和記錄CPU執行軟體的過程,把動態的瞬間“凝固”下來,以供檢查和分析。

軟體除錯的基本目標是定位軟體中存在的設計錯誤(bug)。但除此之外,軟體除錯技術和工具還有很多其他用途,比如分析軟體的工作原理、分析系統崩潰、輔助解決系統和硬體問題等。

綜上所述,軟體是通過指令的組合來指揮硬體,既簡單又複雜,是個充滿神祕與挑戰的世界。而軟體除錯是幫助人們探索和征服這個神祕世界的有力工具。

簡介

本文首先給出軟體除錯的解釋性定義,然後介紹軟體除錯的基本過程。

1.1.1 定義

什麼是軟體除錯?我們不妨從英文的原詞software debug說起。debug是在bug一詞前面加上詞頭de,意思是分離和去除bug。

bug的本意就是“昆蟲”,但早在19世紀時,人們就開始用這個詞來描述電子裝置中的設計缺欠。著名發明家托馬斯·阿爾瓦·愛迪生(1847—1931)就用這個詞來描述電路方面的設計錯誤。

1947年9月9日,當人們測試Mark II計算機時,它突然發生了故障。經過幾個小時的檢查後,工作人員發現一隻飛蛾被打死在面板F的第70號繼電器中。取出這隻飛蛾後,計算機便恢復了正常。當時為Mark II計算機工作的著名女科學家Grace Hopper將這隻飛蛾貼上到了當天的工作手冊中(見圖1-1),並在上面加了一行註釋——“First actual case of bug being found”,當時的時間是15:45。

隨著這個故事的廣為流傳,越來越多的人開始用bug一詞來指代計算機中的設計錯誤,並把Grace Hopper登記的那隻飛蛾看作計算機歷史上第一個記錄於文件(documented)中的bug。

圖1-1 計算機歷史上第一個記錄於文件中的bug

在bug一詞廣泛使用後,人們自然地開始用debug這個詞來泛指排除錯誤的過程。關於誰最先創造和使用了這個詞,目前還沒有公認的說法,但可以肯定的是,Grace Hopper在20世紀50年代發表的很多論文中就已頻繁使用這個詞了。

因此可以肯定地說,在20世紀50年代,人們已經開始用這個詞來表達軟體除錯這一含義,而且一直延續到了今天。

儘管從字面上看,debug的直接意思就是去除bug,但它實際上包含了尋找和定位bug。因為去除bug的前提是要找到bug,如何找到bug大都比發現後去除它要難得多。而且,隨著計算機系統的發展,軟體除錯已經變得越來越不像在繼電器間“捉蟲”那樣輕而易舉了。

因此,在我國臺灣地區,人們把software debug翻譯為“軟體偵錯”。這個翻譯沒有按照英文原詞直譯,超越了單指“去除”的原意,融入了“偵查”的含義,是個很不錯的意譯。

在我國,我們通常將software debug翻譯為“軟體除錯”,泛指重現軟體故障、定位故障根源並最終解決軟體問題的過程。

對軟體除錯另一種更寬泛的解釋是指使用除錯工具求解各種軟體問題的過程,例如跟蹤軟體的執行過程,探索軟體本身或與其配套的其他軟體,或者硬體系統的工作原理等,這些過程有可能是為了去除軟體缺欠,也可能不是。

1.1.2 基本過程

儘管取出那隻飛蛾非常輕鬆,但為了找到它還是耗費了幾個小時的時間。因此,軟體除錯從一開始實際上就包含了定位錯誤和去除錯誤這兩個基本步驟。進一步講,一個完整的軟體除錯過程是圖1-2所示的迴圈過程,它由以下幾個步驟組成。

圖1-2 軟體除錯過程

第一,重現故障,通常是在用於除錯的系統上重複導致故障的步驟,使要解決的問題出現在被除錯的系統中。

第二,定位根源,即綜合利用各種除錯工具,使用各種除錯手段尋找導致軟體故障的根源。通常測試人員報告和描述的是軟體故障所表現出的外在症狀,比如介面或執行結果中所表現出的異常;或者是與軟體需求和功能規約不符的地方,即所謂的軟體缺欠。

而這些表面的缺欠總是由一個或多個內在因素導致的,這些內因要麼是程式碼的行為錯誤,要麼是“不行為”(該做而未做)錯誤。定位根源就是要找到導致外在缺欠的內因。

第三,探索和實現解決方案,即根據找到的故障根源、資源情況、緊迫程度等設計和實現解決方案。

第四,驗證方案,在目標環境中測試方案的有效性,又稱為迴歸(regress)測試。如果問題已經解決,那麼就可以關閉問題;如果沒有解決,則回到第三步調整和修改解決方案。

在以上各步驟中,定位根源常常是最困難也是最關鍵的步驟,它是軟體除錯過程的核心。如果沒有找到故障根源,那麼解決方案便很可能是隔靴搔癢或者頭痛醫腳,有時似乎緩解了問題,但事實上沒有徹底解決問題,甚至是白白浪費時間。

分類

根據被除錯軟體的特徵、所使用的除錯工具以及軟體的執行環境等要素,可以把軟體除錯分成很多個子類。本節將介紹幾種常用的分類方法,並介紹每一種分類方法中的典型除錯任務。

1.2.1 按除錯目標的系統環境分類

軟體除錯所使用的工具和方法與作業系統有著密切的關係。例如,很多偵錯程式是針對作業系統所設計的,只能在某一種或幾種作業系統上執行。對軟體除錯的一種基本分類標準就是被除錯程式(除錯目標)所執行的系統環境(作業系統)。

按照這個標準,我們可以把除錯分為Windows下的軟體除錯、Linux下的軟體除錯、DOS下的軟體除錯,等等。

這種分類方法主要是針對編譯為機器碼的本地(native)程式而言的。對於使用Java和.NET等動態語言所編寫的執行在虛擬機器中的程式,它們具有較好的跨平臺特性,與作業系統的關聯度較低,因此不適用於這種分類方法(見下文)。

1.2.2 按目的碼的執行方式分類

指令碼語言具有簡單易學、不需要編譯等優點,比如網頁開發中廣泛使用的JavaScript和VBScript。指令碼程式是由專門的解釋程式解釋執行的,不需要產生目的碼,與編譯執行的程式有很多不同。除錯使用指令碼語言編寫的指令碼程式的過程稱為指令碼除錯。所使用的偵錯程式稱為指令碼偵錯程式。

編譯執行的程式又主要分成兩類:一類是先編譯為中間程式碼,在執行時再動態編譯為當前CPU能夠執行的目的碼,典型的代表便是使用C#開發的.NET程式。另一類是直接編譯和連結成目的碼的程式,比如傳統的C/C++程式。

為了便於區分,針對前一類程式碼的除錯一般稱為託管除錯,針對後一類程式的除錯稱為本地除錯。如果希望在同一個除錯會話中既除錯託管程式碼又除錯原生代碼,那麼這種除錯方式稱為混合除錯。

 

圖1-3歸納出了按照執行和編譯方式來對軟體除錯進行分類的判斷方法和步驟。

圖1-3 按照執行和編譯方式對軟體除錯進行分類的判斷方法和步驟

1.2.3 按目的碼的執行模式分類

在Windows這樣的多工作業系統中,作為保證安全和秩序的一個根本措施,系統定義了兩種執行模式,即低特權級的使用者模式和高特權級的核心模式。

應用程式程式碼是執行在使用者模式下的,作業系統的核心、執行體和大多數裝置驅動程式則是執行在核心模式的。因此,根據被除錯程式的執行模式,我們可以把軟體除錯分為使用者態除錯和核心態除錯。

因為執行在核心態的程式碼主要是原生代碼以及很少量的指令碼,例如ASL語言編寫的ACPI指令碼,所以核心態除錯主要是除錯原生代碼。而使用者態除錯包括除錯本地應用程式和除錯託管應用程式等。1.2.4 按偵錯程式與除錯目標的相對位置分類

如果被除錯程式(除錯目標)和偵錯程式在同一個計算機系統中,那麼這種除錯稱為本機除錯。這裡的同一個計算機系統是指在同一臺計算機上的同一個作業系統中,不包括執行在同一個物理計算機上的多個虛擬機器。

如果偵錯程式和被除錯程式分別位於不同的計算機系統中,它們通過乙太網絡或其他網路進行通訊,那麼這種除錯方式稱為遠端除錯。遠端除錯通常需要在被除錯程式所在的系統中執行一個除錯伺服器程式。這個伺服器程式和遠端的偵錯程式相互聯絡,向偵錯程式報告除錯事件,並執行偵錯程式下達的命令。

利用Windows核心除錯引擎所做的活動核心除錯需要使用兩臺機器,兩者之間通過序列介面、1394介面或USB 2.0進行連線。儘管這種除錯的偵錯程式和除錯目標也在兩臺機器中,但是通常不將其歸入遠端除錯的範疇。

1.2.5 按除錯工具分類

軟體除錯也可以根據所使用的工具進行分類。最簡單的就是按照除錯時是否使用偵錯程式分為使用偵錯程式的軟體除錯和不使用偵錯程式的軟體除錯。

使用偵錯程式的除錯可以使用斷點、單步執行、跟蹤執行等強大的除錯功能。不使用偵錯程式的除錯主要依靠除錯資訊輸出、日誌檔案、觀察記憶體和檔案等。後者具有簡單的優點,適用於除錯簡單的問題或無法使用偵錯程式的情況。

以上介紹了軟體除錯的幾種常見分類方法,目的是讓讀者對典型的軟體除錯任務有概括性的瞭解。有些分類方法是有交叉性的,比如除錯瀏覽器中的JavaScript屬於指令碼除錯,也屬於使用者態除錯。

除錯技術概覽

深入介紹各種軟體除錯技術是本書的主題,本著循序漸進的原則,在本文中,我們先概述各種常用的軟體除錯技術,幫助大家建立起一個總體印象。

1.3.1 斷點

斷點是使用偵錯程式進行除錯時最常用的除錯技術之一。其基本思想是在某一個位置設定一個“陷阱”,當CPU執行到這個位置時便“跌入陷阱”,即停止執行被除錯的程式,中斷到偵錯程式中,讓除錯者進行分析和除錯。除錯者分析結束後,可以讓被除錯程式恢復執行。

根據斷點的設定空間可以把斷點分為如下幾種。

(1)程式碼斷點:設定在記憶體空間中的斷點,其地址通常為某一段程式碼的起始處。當CPU執行指定記憶體地址的程式碼(指令)時斷點命中(hit),中斷到偵錯程式。使用偵錯程式的圖形介面或快捷鍵在某一行原始碼或彙編程式碼處設定的斷點便是程式碼斷點。

(2)資料斷點:設定在記憶體空間中的斷點,其地址一般為所要監視變數(資料)的起始地址。當被除錯程式訪問指定記憶體地址的資料時斷點命中。根據需要,測試人員可以定義觸發斷點的訪問方式(讀/寫)和寬度(位元組、字、雙字等)。

(3)I/O斷點:設定在I/O空間中的斷點,其地址為某一I/O地址。當程式訪問指定I/O地址的埠時中斷到偵錯程式。與資料斷點類似,測試人員也可以根據需要設定斷點被觸發的訪問寬度。

根據斷點的設定方法,我們可以把斷點分為軟體斷點和硬體斷點。軟體斷點通常是通過向指定的程式碼位置插入專用的斷點指令來實現的,比如IA32 CPU的INT 3指令(機器碼為0xCC)就是斷點指令。

硬體斷點通常是通過設定CPU的除錯暫存器來設定的。IA32 CPU定義了8個除錯暫存器:DR0~DR7,可以同時設定最多4個硬體斷點(對於一個除錯會話)。通過除錯暫存器可以設定以上3種斷點中的任意一種,但是通過斷點指令只可以設定程式碼斷點。

當中斷到偵錯程式時,系統或偵錯程式會將被除錯程式的狀態儲存到一個數據結構中——通常稱為執行上下文(CONTEXT)。中斷到偵錯程式後,被除錯程式是處於靜止狀態的,直到使用者輸入恢復執行命令。

追蹤點是斷點的一種衍生形式。其基本思路是:當設定一個追蹤點時,偵錯程式內部會當作特殊的斷點來處理。當執行到追蹤點時,系統會向偵錯程式報告斷點事件,在偵錯程式收到後,會檢查內部維護的斷點列表,發現目前發生的是追蹤點後,便執行這個追蹤點所定義的行為,通常是列印提示資訊和變數值,然後便直接恢復被除錯程式執行。

因為偵錯程式是在執行追蹤動作後立刻恢復被除錯程式執行的,所以除錯者沒有感覺到被除錯程式中斷到偵錯程式的過程,儘管實際上是發生的。

條件斷點的工作方式也與此類似。當用戶設定一個條件斷點時,偵錯程式實際插入的還是一個無條件斷點,在斷點命中、偵錯程式收到除錯事件後,它會檢查這個斷點的附加條件。如果條件滿足,便中斷給使用者,讓使用者開始互動式除錯;如果不滿足,那麼便立刻恢復被除錯程式執行。

1.3.2 單步執行

單步執行是最早的除錯方式之一。簡單來說,就是讓應用程式按照某一步驟單位一步一步執行。

根據每次要執行的步驟單位,又分為如下幾種。

(1)每次執行一條彙編指令,稱為組合語言一級的單步跟蹤。其實現方法一般是設定CPU的單步執行標誌,以IA32 CPU為例,設定CPU標誌暫存器的陷阱標誌(Trap Flag,TF)位,可以讓CPU每執行完一條指令便產生一個除錯異常(INT 1),中斷到偵錯程式。

(2)每次執行原始碼(比組合語言更高階的程式語言,如C/C++)的一條語句,又稱為原始碼級的單步跟蹤。高階語言的單步執行一般也是通過多次彙編一級的單步執行實現的。

當偵錯程式每次收到除錯事件時,它會判斷程式指標(IP)是否還屬於當前的高階語言語句,如果是,便再次設定單步執行標誌並立刻恢復執行,讓CPU再執行一條彙編指令,直到程式指標指向的彙編指令已經屬於其他語句。偵錯程式通常是通過符號檔案中的原始碼行資訊來判斷程式指標所屬於的原始碼行的。

(3)每次執行一個程式分支,又稱為分支到分支單步跟蹤。設定IA32 CPU的DbgCtl MSR暫存器的BTF(Branch Trap Flag)標誌後,再設定TF標誌,便可以讓CPU執行到下一個分支指令時觸發除錯異常。WinDBG的tb命令用來執行到下一個分支。

(4)每次執行一個任務(執行緒),即當指定任務被排程執行時中斷到偵錯程式。當IA32 CPU切換到一個新的任務時,它會檢查任務狀態段(TSS)的T標誌。如果該標誌為1,那麼便產生除錯異常。但目前的偵錯程式大多還沒有提供對應的功能。

單步執行可以跟蹤程式執行的每一個步驟,觀察程式碼的執行路線和資料的變化過程,是深入診斷軟體動態特徵的一種有效方法。但是隨著軟體向大型化方向的發展,從頭到尾跟蹤執行一個軟體乃至一個模組,一般都不再可行了。一般的做法是先使用斷點功能將程式中斷到感興趣的位置,然後再單步執行關鍵的程式碼。我們將在第4章詳細介紹CPU的單步執行除錯。

1.3.3 輸出除錯資訊

列印和輸出除錯資訊是一種簡單而“古老”的軟體除錯方式。其基本思想就是在程式中編寫專門用於輸出除錯資訊的語句,將程式執行的位置、狀態和變數取值等資訊以文字的形式輸出到某一個可以觀察到的地方,可以是控制檯、視窗、檔案或者偵錯程式。

比如,在Windows平臺上,驅動程式可以使用DbgPrint/DbgPrintEx來輸出除錯資訊,應用程式可以呼叫OutputDebugString,控制檯程式可以直接使用printf系列函式列印資訊。在Linux平臺上,驅動程式可以使用printk來輸出除錯資訊,應用程式可以使用printf系列函式。

以上方法的優點是簡單方便、不依賴於偵錯程式和複雜的工具,因此至今仍在很多場合廣泛使用。

不過這種簡單方式也有一些明顯的缺點,比如需要在被除錯程式中加入程式碼,如果被除錯程式的某個位置沒有列印語句,那麼便無法觀察到那裡的資訊,如果要增加列印語句,那麼需要重新編譯和更新程式。

另外,這種方法容易影響程式的執行效率,打印出的文字所包含的資訊有限,容易洩漏程式的技術細節,通常不可以動態開啟、資訊不是結構化的、難以分析和整理等。我們將在16.5.2節介紹使用這種方法應該注意的一些細節。

1.3.4 日誌

與輸出除錯資訊類似,寫日誌(log)是另一種被除錯程式自發的輔助除錯手段。其基本思想是在編寫程式時加入特定的程式碼將程式執行的狀態資訊寫到日誌檔案或資料庫中。

日誌檔案通常自動按時間取檔名,每一條記錄也有詳細的時間資訊,因此適合長期儲存以及事後檢查與分析。因此很多需要連續長時間在後臺執行的伺服器程式都有日誌機制。

Windows作業系統提供了基本的日誌記錄、觀察和管理(刪除和備份)功能。Windows Vista新引入了名為Common Log File System(CLFS.SYS)的核心模組,用於進一步加強日誌功能。Syslog是Linux系統下常用的日誌設施。

1.3.5 事件追蹤

列印除錯資訊和日誌都是以文字形式來輸出和記錄資訊的,因此不適合處理資料量龐大且速度要求高的情況。事件追蹤機制(Event Trace)正是針對這一需求設計的,它使用結構化的二進位制形式來記錄資料,觀察時再根據格式檔案將資訊格式轉化為文字形式,因此適用於監視訊繁且複雜的軟體過程,比如監視檔案訪問和網路通訊等。

ETW(Event Trace for Windows)是Windows作業系統內建的一種事件追蹤機制,Windows核心本身和很多Windows下的軟體工具(如Bootvis、TCP/IP View)都使用了該機制。我們將在第16章詳細介紹事件追蹤機制及其應用

1.3.6 棧回溯

目前的主流CPU架構都是用棧來進行函式呼叫的,棧上記錄了函式的返回地址,因此通過遞迴式尋找放在棧上的函式返回地址,便可以追溯出當前執行緒的函式呼叫序列,這便是棧回溯的基本原理。通過棧回溯產生的函式呼叫資訊稱為call stack(函式呼叫棧)。

棧回溯是記錄和探索程式執行蹤跡的極佳方法,使用這種方法,可以快速瞭解程式的執行軌跡,看其“從哪裡來,向哪裡去”。

因為從棧上得到的只是函式返回地址(數值),不是函式名稱,所以為了便於理解,可以利用除錯符號(debug symbol)檔案將返回地址翻譯成函式名。大多數編譯器都支援在編譯時生成除錯符號。微軟的除錯符號伺服器包含了多個Windows版本的系統檔案的除錯符號。我們將在本書後續分卷深入討論除錯符號。

大多數偵錯程式都提供了棧回溯的功能,比如WinDBG的k命令和GDB的bt命令,它們都是用來觀察棧回溯資訊的,某些非偵錯程式工具也可以記錄和呈現棧回溯資訊。

重要性

從軟體工程的角度來講,軟體除錯是軟體工程的一個重要部分,軟體調試出現在軟體工程的各個階段。從最初的可行性分析、原型驗證到開發和測試階段,再到釋出後的維護與支援,都需要軟體除錯技術。

定位和修正bug是幾乎所有軟體專案的重要問題,越臨近釋出,這個問題的重要性越高!很多軟體專案的延期是由於無法在原來的期限內修正bug所造成的。

為了解決這個問題,整個軟體團隊都應該重視軟體的可除錯性,重視對軟體除錯風險的評估和預測,並預留時間。

1.4.1 除錯與編碼的關係

除錯與編碼(coding)是軟體開發中不同但聯絡密切的兩個過程。在軟體的開發階段,對於一個模組(一段程式碼)來說,它的編寫者通常也是它的除錯者。或者說,一個程式設計師要負責除錯他所編寫的程式碼。這樣做有兩個非常大的好處。

(1)除錯過程可以讓程式設計師瞭解程式的實際執行過程,檢驗執行效果與自己設計時的預想是否一致,如果不一致,那麼很可能預示著程式碼存在問題,應該引起重視。

(2)除錯過程可以讓程式設計師更好地認識到提高程式碼可除錯性和程式碼質量的重要性,進而讓他們自覺改進編碼方式,合理新增可用來支援除錯的程式碼。

編碼和除錯是程式設計師日常工作中兩項最主要的任務,這兩項任務是相輔相成的,編寫具有可除錯性的高質量程式碼可以明顯提高除錯效率,節約除錯時間。此外,除錯可以讓程式設計師真切感受程式的實際執行過程,反思編碼和設計中的問題,加深對軟體和系統的理解,提高對程式碼的感知力和控制力。

在軟體釋出後,有些除錯任務是由技術支援人員來完成的,但是當他們將錯誤定位到某個模組並且無法解決時,有時還要找到它的本來設計者。

很多經驗豐富的程式設計師都把除錯放在頭等重要的位置,他們會利用各種除錯手段觀察、跟蹤和理解程式碼的執行過程。通過除錯,他們可以發現編碼和設計中的問題,並把這些問題在釋出給測試人員之前便糾正了。

於是,人們認為他們編寫程式碼的水平非常高,沒有或者很少有bug,在團隊中有非常好的口碑。對於測試人員發現的問題,他們也彷彿先知先覺,看了測試人員的描述後,一般很快就能意識到問題所在,因為他們已經通過除錯把程式碼的靜態和動態特徵都放在大腦中了,對其瞭然於胸。

但也有些程式設計師很少跟蹤和除錯他們編寫的程式碼,也不知道這些程式碼何時被執行以及執行多少次。對於測試人員報告的一大堆問題,他們也經常是一頭霧水,不知所措。

毋庸置疑,忽視除錯對於提高程式設計師的程式設計水平和綜合能力都是很不利的。因此,《Debugging by Thinking》一書的作者Robert Charles Metzger說道:“導致今天的軟體有如此多缺欠的原因有很多,其中之一就是很多程式設計師不擅長除錯,一些程式設計師對待軟體除錯就像對待個人所得稅申報表那樣消極。”

1.4.2 除錯與測試的關係

簡單地說,測試的目的是在不知道有問題存在的情況下去尋找和發現問題,而除錯是在已經知道問題存在的情況下定位問題根源。從因果關係的角度來看,測試是旨在發現軟體“表面”的不當行為和屬性,而除錯是尋找這個表象下面的內因。因此二者是有明顯區別的,儘管有些人時常將它們混淆在一起。

測試與除錯的宗旨是一致的,那就是軟體的按期交付。為了實現這一共同目標,測試人員與除錯人員應該相互尊重,密切配合。例如,測試人員應該儘可能準確詳細地描述缺欠,說明錯誤的症狀、實際的結果和期待的結果、發現問題的軟硬體環境、重現問題的方法以及需要注意的細節。

測試人員應該在軟體中加入檢查錯誤和輔助除錯的手段,以便更快地定位問題。

軟體的除錯版本應包含更多的錯誤檢查環節,以便更容易測試出錯誤,因此除了測試軟體的釋出版本外,測試除錯版本是提高測試效率、加快整個專案進度的有效措施。

1.4.3 除錯與逆向工程的關係

典型的軟體開發過程是設計、編碼,再編譯為可執行檔案(目標程式)的過程。因此,所謂逆向工程就是根據可執行檔案反向推匯出編碼方式和設計方法的過程。

偵錯程式是逆向工程中的一種主要工具。符號檔案、跟蹤執行、變數監視和觀察以及斷點這些軟體除錯技術都是實施逆向工程時經常使用的技術手段。

逆向工程的合法性依賴於很多因素,需要視軟體的授權協議、所在國家的法律、逆向工程的目的等具體情況而定,其細節超出了本書的討論範圍。​

​《軟體除錯(第2版)卷1:硬體基礎》

張銀奎 著

本書堪稱是軟體除錯的“百科全書”。作者圍繞軟體除錯的“生態”系統、異常和偵錯程式 3 條主線,介紹軟體除錯的相關原理和機制,探討可除錯性(debuggability)的內涵、意義以及實現軟體可除錯性的原則和方法,總結軟體除錯的方法和技巧。

第1卷主要圍繞硬體技術展開介紹。全書分為4篇,共16章。第一篇“緒論”(第1章),介紹了軟體除錯的概念、基本過程、分類和簡要歷史,並綜述了本書後面將詳細介紹的主要除錯技術。第二篇“CPU及其除錯設施”(第2~7章),以英特爾和ARM架構的CPU為例系統描述了CPU的除錯支援。第三篇“GPU及其除錯設施”(第8~14章),深入探討了Nvidia、AMD、英特爾、ARM和Imagination 這五大廠商的GPU。第四篇“可除錯性”(第15~16章),介紹了提高軟體可除錯性的意義、基本原則、例項和需要注意的問題,並討論瞭如何在軟體開發實踐中實現可除錯性。

邀請10名好友關注非同步圖書10天,即可免費獲得非同步新書。

長按二維碼,可以關注我們喲

每天與你分享IT好文。

點選閱讀原文,購買軟體除錯(第2版)卷1:硬體基礎

閱讀原文