




已閱讀5頁(yè),還剩8頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
軟件測(cè)試:調(diào)試(DEBUGGING)簡(jiǎn)單地講,調(diào)試是執(zhí)行一次成功的測(cè)試之后所要進(jìn)行的工作。記住,所謂成功 的測(cè)試,是指它可以證明程序沒(méi)有實(shí)現(xiàn)預(yù)期的功能。調(diào)試是一個(gè)包含兩個(gè)步驟的過(guò) 程,從執(zhí)行了一個(gè)成功的測(cè)試用例、發(fā)現(xiàn)了一個(gè)問(wèn)題之后開(kāi)始。第一步,確定程序 中可疑錯(cuò)誤的準(zhǔn)確性質(zhì)和位置;第二步,修改錯(cuò)誤。雖然調(diào)試對(duì)于程序測(cè)試來(lái)說(shuō)非常必要、不可或缺,但它似乎是軟件開(kāi)發(fā)過(guò)程中 最不受程序員歡迎的部分之一。其主要原因可能包括以下幾點(diǎn):個(gè)人自尊會(huì)從中阻撓。不管我們是否喜歡,調(diào)試都說(shuō)明了程序員并不完美, 要么在軟件的設(shè)計(jì),要么在程序編碼時(shí)會(huì)犯錯(cuò)。熱情耗盡。在所有的軟件開(kāi)發(fā)活動(dòng)中,調(diào)試是最耗費(fèi)腦力的苦差事,況且, 進(jìn)行調(diào)試往往經(jīng)受著來(lái)自機(jī)構(gòu)或自身的巨大壓力,必須盡可能快地改正問(wèn) 題??赡軙?huì)迷失方向。調(diào)試是艱苦的腦力工作,因?yàn)榘l(fā)現(xiàn)的錯(cuò)誤實(shí)際上可能會(huì) 出現(xiàn)在程序的任何語(yǔ)句中。也就是說(shuō),如果不首先檢查程序,我們就不能 絕對(duì)地肯定在一個(gè)薪金管理程序出具的支票中出現(xiàn)的數(shù)字錯(cuò)誤不是由某個(gè) 子程序引起的,該子程序要求操作員將一個(gè)特定的表格傳輸給打印機(jī)。讓 我們以診斷一個(gè)物理系統(tǒng)為例子作對(duì)比,如汽車。假如汽車在爬坡時(shí)熄火 了(癥狀),那么我們可能會(huì)迅速而有效地排除掉某些部件調(diào)頻/調(diào)幅 收音機(jī)、速度表或汽車門鎖引起該故障的可能。根據(jù)我們對(duì)汽車引擎 的整體了解,該故障一定是發(fā)生在引擎上,我們甚至可以排除掉某些引擎 部件,如水箱和濾油器。必須自力更生。與其他軟件開(kāi)發(fā)活動(dòng)相比,關(guān)于調(diào)試過(guò)程的研究、資料和 正式的指南都比較少。盡管本書(shū)是關(guān)于軟件測(cè)試的,并不討論調(diào)試,但這兩個(gè)過(guò)程顯然是相互聯(lián)系的。 針對(duì)調(diào)試的兩個(gè)步驟,即錯(cuò)誤定位和錯(cuò)誤修改,對(duì)錯(cuò)誤進(jìn)行定位可能解決了 95的問(wèn)題。因此,本章集中討論錯(cuò)誤的定位過(guò)程,當(dāng)然是假定某個(gè)成功的測(cè)試用例已經(jīng)發(fā)現(xiàn)了一個(gè)錯(cuò)誤。7.1 暴力法調(diào)試(Debugging by Brute Force)調(diào)試程序的最為普遍的模式是所謂的“暴力”方法。這種方法之所以流行,是 因?yàn)樗恍枰^(guò)多思考,是耗費(fèi)腦力最少的方法,但同時(shí)也效率低下,通常來(lái)講不 是很成功。暴力調(diào)試方法可至少被劃分為三種類型:1.利用內(nèi)存信息輸出來(lái)調(diào)試。2.根據(jù)一般的“在程序中插入打印語(yǔ)句”建議來(lái)調(diào)試。3.使用自動(dòng)化的調(diào)試工具進(jìn)行調(diào)試。 第一種類型,使用內(nèi)存信息輸出(通常使用十六進(jìn)制或八進(jìn)制格式粗略地顯示所有的存儲(chǔ)區(qū)域)是最缺乏效率的暴力調(diào)試方法,原因如下:難以在內(nèi)存區(qū)域?qū)懺闯绦蛑械淖兞恐g建立對(duì)應(yīng)關(guān)系。即使對(duì)下復(fù)雜程度較低的程序,內(nèi)存信息輸出也會(huì)產(chǎn)生數(shù)最非常龐大的數(shù) 據(jù),其中的大多數(shù)都是與調(diào)試無(wú)關(guān)的。內(nèi)存信息輸出顯示的是程序的靜態(tài)快照,僅能顯示出在某一個(gè)時(shí)刻程序的 狀態(tài);為了發(fā)現(xiàn)錯(cuò)誤,還需要研究程序的動(dòng)態(tài)狀態(tài)(隨時(shí)間的狀態(tài)變化)。內(nèi)存信息輸出很少可以精確地在錯(cuò)誤發(fā)生的地方產(chǎn)生,因此無(wú)法顯示在錯(cuò) 誤發(fā)生時(shí)程序的狀態(tài)。錯(cuò)誤發(fā)生到輸出內(nèi)存信息這段時(shí)間之內(nèi)程序執(zhí)行的 活動(dòng),可能會(huì)掩蓋掉發(fā)現(xiàn)錯(cuò)誤所需的線素。通過(guò)分析輸出的內(nèi)存信息來(lái)發(fā)現(xiàn)問(wèn)題的方法并不大多(因此很名程序員都 是密切注視,急切地渴望著錯(cuò)誤能神奇地從內(nèi)存信息輸出中自行暴露出 來(lái))。第二種類型,在失效的程序中插入輸出變量值的語(yǔ)句,這種做法也不具有很強(qiáng) 的優(yōu)勢(shì)。它可能比內(nèi)存信息輸出要好一些,因?yàn)榭梢燥@示程序的動(dòng)態(tài)狀態(tài),讓我們 檢查的信息可以相對(duì)容易地與源程序聯(lián)系起來(lái)。但是這種方法同樣也有很多缺點(diǎn):它不是鼓勵(lì)我們?nèi)ニ伎汲绦蛑械膯?wèn)題,而主要是一種碰運(yùn)氣的方法。它所產(chǎn)生的需要分析的數(shù)據(jù)量非常龐大。它要求我們修改程序,這些修改可能會(huì)掩蓋掉錯(cuò)誤、改變關(guān)鍵的時(shí)序關(guān)系, 或者會(huì)引入新的錯(cuò)誤。它可能對(duì)小型程序有效,但如果應(yīng)用到大型程序,成本就相當(dāng)高。況且對(duì) 于某些類型的程序,如操作系統(tǒng)或過(guò)程控制軟件,這種辦法甚至無(wú)法使用。第三種類型,自動(dòng)化調(diào)試工具的工作機(jī)制類似于在程序中插入打印語(yǔ)句, 但是并不修改程序本身??梢允褂镁幊陶Z(yǔ)言的調(diào)試功能,或使用特殊的交互式 調(diào)試工具來(lái)分析程序的動(dòng)態(tài)狀態(tài)??赡軙?huì)用到的典型的語(yǔ)言功能有:產(chǎn)生可打 印的語(yǔ)句執(zhí)行軌跡的機(jī)制、子程序調(diào)用以及/或者對(duì)特定變量的修改等。調(diào)試工 具的一個(gè)共同的功能是可以設(shè)置斷點(diǎn),使程序在執(zhí)行到某條特定語(yǔ)句或改動(dòng)了 某個(gè)特定變量的值時(shí)暫停執(zhí)行,然后程序員就可以檢查程序的當(dāng)前狀態(tài)。同樣, 這種方法也主要是在碰運(yùn)氣,常常會(huì)生成數(shù)量過(guò)于龐大的無(wú)關(guān)數(shù)據(jù)。這些暴力調(diào)試方法的主要問(wèn)題在于:它們都忽略了思考的過(guò)程。我們可以 在調(diào)試程序和偵破謀殺案之間找出相似點(diǎn)來(lái)。實(shí)際上,在幾平所有的謀殺懸念 小說(shuō)中,謎案都是通過(guò)仔細(xì)分析線索,將表面上不重要的細(xì)節(jié)全聯(lián)結(jié)起來(lái)而最 終偵破的。這不是一個(gè)使用蠻力的方法,要使用蠻力的是尋覓障礙物或搜尋財(cái) 寶。還有些證據(jù)表明,無(wú)論調(diào)試小組成員是富有經(jīng)驗(yàn)的程序員還是學(xué)生,肯動(dòng) 腦筋而不是依賴別人幫助的人能夠更快、更準(zhǔn)確地發(fā)現(xiàn)程序錯(cuò)誤。因此,我們 建議僅在下列情況下使用暴力調(diào)試方法:(l)其他的方法都失敗了:(2)作為 我們下面將會(huì)討論的思考過(guò)程的補(bǔ)充,而不是替代方法。7.2 歸納法調(diào)試(Debugging by Induction)很顯然,認(rèn)真的思考能夠發(fā)現(xiàn)大部分錯(cuò)誤,甚至不需要調(diào)試人員使用調(diào)試 工具歸納是一種特殊的思考過(guò)程,可以從細(xì)節(jié)轉(zhuǎn)到全局,也就是從線索(即 錯(cuò)誤的癥狀,可能是一個(gè)或多個(gè)測(cè)試用例的結(jié)果)出發(fā),尋找線索之間的聯(lián)系。 歸納的過(guò)程如圖 7-1 所示。不能數(shù)據(jù)組織數(shù)據(jù)間聯(lián)系構(gòu)造假設(shè)能證明假設(shè)不能 能修改錯(cuò)誤圖 7-1 使用歸納法的調(diào)試過(guò)程歸納調(diào)試的步驟如下:1.確定相關(guān)數(shù)據(jù)。調(diào)試人員犯的一個(gè)主要錯(cuò)誤是未能將所有可用的數(shù)據(jù)或癥 狀都考慮進(jìn)去。第一步是列舉出所有知道的程序執(zhí)行的正確和不正確之處, 這些不正確之處即是癥狀,讓我們相信確實(shí)存在錯(cuò)誤。那些相似卻不相同、 且未引起癥狀出現(xiàn)的測(cè)試用例提供了額外的有價(jià)值的線索。2.組織數(shù)據(jù)。記住,歸納意味著從特殊到一般,因此第二步是組織這些相關(guān) 數(shù)據(jù),以便觀察線索間的模式,尤其重要的是要找到矛盾、事件,比如僅 當(dāng)客戶的保險(xiǎn)金賬戶收支不太平衡時(shí)出現(xiàn)的錯(cuò)誤。我們可以采用圖 7-2 所 示的表格來(lái)組織現(xiàn)有的數(shù)據(jù)?!笆鞘裁础笨蛄信e的是總體的癥狀,“在何處” 框描述了這些癥狀出現(xiàn)的地方,“多大程度”框描述了這些癥狀的范圍和重 要性。注意“是”和“否列,它們所描述的矛盾之處最終可能會(huì)導(dǎo)致對(duì)錯(cuò)誤的假設(shè)。?IsIs notWhatWhereWhenTo what next圖 7-2 組織線索的一種方法3.做出假設(shè)。下一步是研究線索之間的聯(lián)系,利用線索結(jié)構(gòu)里可能的模式做 出一個(gè)或多個(gè)關(guān)于錯(cuò)誤原因的假設(shè)。如果還無(wú)法做出推測(cè),就需要更多的數(shù)據(jù)。如果可能有多個(gè)假設(shè)存在,首先選擇最有能的一個(gè)。4.證明假設(shè)??紤]到調(diào)試在進(jìn)行時(shí)所承受的壓力,這個(gè)時(shí)期最主要的錯(cuò)誤是 忽略了這個(gè)階段,直接跳到結(jié)論去改正問(wèn)題。但是在繼續(xù)下一步之前,證 明這些假設(shè)的合理性是非常重要的。如果忽略了這一步,可能接下去只修 改了問(wèn)題癥狀,而沒(méi)解決問(wèn)題本身。應(yīng)將假設(shè)與其最初的線索或數(shù)據(jù)相比 較,以此來(lái)證明假設(shè)的合理性,確定這些假設(shè)可以完全解釋這些線索的存 在。如果無(wú)法解釋,要么這些假設(shè)是無(wú)效的或不完整的,要么還有更多的 錯(cuò)誤存在。舉一個(gè)簡(jiǎn)單的例子、假設(shè)在第 4 章描述的考試評(píng)分軟件報(bào)告了一個(gè)明顯的錯(cuò) 誤。錯(cuò)誤是在某些但不是所有情況下,中間值似乎不正確。在某個(gè)特殊的測(cè)試用例 中,有 51 名學(xué)生被評(píng)分。正確打印出宋的平均分?jǐn)?shù)為 73.2,但打印出的中間值是26 分,而不是預(yù)期的 82 分。經(jīng)過(guò)對(duì)該測(cè)試用例及其他一些測(cè)試用例結(jié)果的檢查,線索按圖 7-3 所示的形式進(jìn)行組織。?IsIs notWhat報(bào)告 3 中顯示的中間值不正確計(jì)算平均值或標(biāo)準(zhǔn)偏差時(shí)出現(xiàn)Where僅在報(bào)告 3 中出現(xiàn)在其它報(bào)告中出現(xiàn)。學(xué)生成績(jī)的計(jì)算似乎正確When當(dāng)測(cè)試學(xué)生為 51 時(shí)發(fā)生在測(cè)試學(xué)生數(shù)量為 2 和 200時(shí)未發(fā)生To what next顯示的中間值為 26。當(dāng)學(xué)生數(shù)量為 1 時(shí)也同樣發(fā)生,顯示 的中間值。圖 7-3 組織線索的例子下一步是通過(guò)尋找模式和矛盾之處,做出關(guān)于該錯(cuò)誤的假設(shè)。我們看到的一個(gè) 矛盾是這個(gè)錯(cuò)誤似乎出現(xiàn)在學(xué)生人數(shù)為奇數(shù)的測(cè)試用例中,這也許是個(gè)巧合,但看 來(lái)很重要,因?yàn)槲覀円鶕?jù)學(xué)生人數(shù)為奇數(shù)或偶數(shù)而不同地計(jì)算中間值。還有一個(gè) 奇怪的模式:在些測(cè)試用例中,計(jì)算出來(lái)的中間值總是小于或等于學(xué)生的人數(shù)(26 小等于 51,l 小等于 1)。這時(shí),一個(gè)可能的方法是再重新運(yùn)行一次學(xué)生人數(shù)為 51 名的測(cè)試用例,給學(xué)生打與以前不同的分?jǐn)?shù),看一下是如何影響中間依的計(jì)算的。 如果中間值仍然是 26,那么“否多大程度”框可以填上“中間值似乎與實(shí)際分 數(shù)無(wú)關(guān)”。盡管這個(gè)結(jié)果提供了一條有價(jià)值的線索,但即使沒(méi)有它,我們可能已經(jīng)能夠猜出這個(gè)錯(cuò)誤來(lái)。從現(xiàn)有數(shù)據(jù)計(jì)算出的中間值似乎等于學(xué)生人數(shù)的一半,經(jīng)過(guò)四舍五入后得到最接近的一個(gè)整數(shù)。換句話說(shuō),如果將分?jǐn)?shù)設(shè)想為存儲(chǔ)在一個(gè)分類 表里,該程序打印的是中間學(xué)生的人數(shù)而不是其成績(jī)。因此,我們有了一個(gè)關(guān)于該 錯(cuò)誤準(zhǔn)確性質(zhì)的堅(jiān)定的假設(shè)。下一步就是通過(guò)檢查代碼或執(zhí)行一些附加的測(cè)試用例 來(lái)證明這個(gè)假設(shè)。7.3 演繹法調(diào)試(Debugging by Deduction)演繹的過(guò)程是從一些普遍的理論或前提出發(fā),使用排除和精煉的過(guò)程,達(dá)到一 個(gè)結(jié)論(錯(cuò)誤的位置),參見(jiàn)圖 7- 4 。130列出可能 的原因使用排除 法提煉剩下 的假設(shè)證明剩下能 的假設(shè)修改錯(cuò)誤都被排除不能收集更多 數(shù)據(jù)圖 7-4 使用演繹法的調(diào)試過(guò)程舉個(gè)謀殺犯的例子,與歸納過(guò)程相反,首先從一系列嫌疑人入手,通過(guò)排除(花 匠有當(dāng)時(shí)不在現(xiàn)場(chǎng)的合理證詞)和提煉(罪犯可能是紅色頭發(fā))的過(guò)程,判斷出管 家可能犯了罪。演繹的步驟如下:1.列舉出所有可能的原因或假設(shè)第一步是建立一份所有想象得到的錯(cuò)誤線 索的清單,線索不需要有完整的解釋,它們純粹是一些推測(cè),幫助我們組 織和分析現(xiàn)有的數(shù)據(jù)。2.利用數(shù)據(jù)排除可能的原因。詳細(xì)檢查所有的數(shù)據(jù),尤其尋找存在矛盾的地 方(圖 7-2 可以用在此處),然后盡量排除所有可能的原因,僅留下一條, 如果所有的原因都排除掉了,需要增加額外的測(cè)試用例,得到更多的數(shù)據(jù) 來(lái)設(shè)計(jì)新的推測(cè)。如果剩下的原因多于一個(gè),那么首先選擇最有可能的原 因,即主要假設(shè)。3.提煉剩下的假設(shè)。此時(shí)的可能原因也許是正確的,但可能不夠具體,不能指出錯(cuò)誤來(lái)。因此,下一步是使用現(xiàn)有的線索來(lái)提煉這個(gè)推側(cè)舉例來(lái)說(shuō),我們可能會(huì)首先想到“對(duì)文件中最后事務(wù)的處理可能存在錯(cuò)誤”,并將其提 煉為“緩沖區(qū)中的最后事務(wù)被文件結(jié)束指示器覆蓋” 。4.證明剩下的假設(shè)。這個(gè)重要步驟與歸納法中的第 4 步驟相同。 舉個(gè)例子,假設(shè)我們著手對(duì)第 4 章討論的 DISPLAY 命令進(jìn)行功能測(cè)試。在由因果圖分析方法確定的 38 個(gè)測(cè)試用例中,我們首先使用 4 個(gè)測(cè)試用例。作為建立輸入條件過(guò)程的一部分,我們對(duì)內(nèi)存進(jìn)行初始化,將第一個(gè)、第五個(gè)、第九個(gè)、 字的值設(shè)置為 0000,將第二個(gè)、第六個(gè)、 字的值設(shè)置為 4444 ,將第三個(gè)、第 七個(gè)、字的值設(shè)置為 8888,將第四個(gè)、第八個(gè)、 字的值設(shè)置為 CCCC。也就 是說(shuō),每個(gè)內(nèi)存字單元都初始化為每個(gè)字的首字節(jié)地址中的低位十六進(jìn)制數(shù)字(23FC、23FD、23FE 和 23FF 地址的值為 C)。圖 7-5 顯示了這些測(cè)試用例、預(yù)期的輸出及測(cè)試用例的實(shí)際輸出。 顯然,我們遇到了一些問(wèn)題,所有的測(cè)試用例都沒(méi)有產(chǎn)生預(yù)期的結(jié)果(全部都成功了)。讓我們從調(diào)試與第一個(gè)測(cè)試用例相關(guān)的錯(cuò)誤開(kāi)始。該命令表明,從 0 地址開(kāi)始(默認(rèn)情況),要顯示 E(十進(jìn)制中的 14)個(gè)地址(回憶一下,規(guī)格說(shuō)明定 義所有的輸出應(yīng)每行包括 4 個(gè)字或 16 個(gè)字節(jié))。測(cè)試用例的輸入預(yù)期的輸出實(shí)際的輸出DISPLAY0000 = 0000 4444 8888 CCCCM1INVALIDCOMMANDSYNTAXDISPLAY 21v-29 0000 4444 8888 CCCC = 4444 8888 CCCC 0000DISPLAY.11 = 0000 4444 8888 CCCC = 0000 4444 8888 CCCC = 0000 4444 8888 CCCCDISPLAY 8000-ENDM2 STORAGE REOUESTED IS BEYONDACTUALMEMORYLIMITS = 0000 4444 8888 CCCC圖 7-5 DISPLAY 命令的測(cè)試用例輸出結(jié)果為出現(xiàn)的不期望的錯(cuò)誤信息列舉可能的原因:1.程序不能接受單詞 DISPLAY。2.程序不能接受句號(hào)。3.程序不允許第一個(gè)操作數(shù)為默認(rèn)情況。程序要求在句號(hào)之前聲明一個(gè)存儲(chǔ) 地址。4.程序不允許 E 作為有效的字節(jié)數(shù)量。下一步是盡力排除這些原因。如果所有原因都排除掉了,那么需要退回去并擴(kuò) 充一下原因的清單。如果剩下來(lái)的原因超過(guò)了一個(gè),那么就需要檢驗(yàn)額外的測(cè)試用 例以確定惟一的錯(cuò)誤假設(shè),或繼續(xù)使用可能性最大的原因。由于我們手上還有其他 測(cè)試用例,可以看到圖 7-5 中的第二個(gè)測(cè)試用例似乎可以排除掉第 1 條假設(shè),而第 三個(gè)測(cè)試用例盡管產(chǎn)生了錯(cuò)誤的結(jié)果,也似乎可以排除掉第 2 和第 3 條假設(shè)。下一步是提煉第 4 條假設(shè)。它看上去足夠具體,但直覺(jué)告訴我們實(shí)質(zhì)的內(nèi)容要 比表面上看到的多。它看上去似乎是一個(gè)更為一般的錯(cuò)誤實(shí)例。那么我們可以認(rèn)為 程序不能正確識(shí)別特殊的十六進(jìn)制字符 AF 。在其他測(cè)試用例中缺少這些字符, 使得這聽(tīng)起來(lái)是一個(gè)行得通的解釋。然而我們不能馬上得出結(jié)論,而應(yīng)該首先考慮 所有的已知信息。第四個(gè)測(cè)試用例可能代表一個(gè)完全不同的錯(cuò)誤,也可能提供了一 條關(guān)于當(dāng)前錯(cuò)誤的線索。假設(shè)系統(tǒng)的最高有效地址是 7FFF,那么第四個(gè)測(cè)試用例 將如何顯示一個(gè)明顯不存在的區(qū)域呢?顯示的值是我們初始化后的值而不是無(wú)用 的信息,這個(gè)事實(shí)讓我們推測(cè)該命令不知何故顯示了 07FFF 之間的某些內(nèi)容。 我們可能會(huì)想到,這種錯(cuò)誤也許會(huì)發(fā)生在程序?qū)⒚畹牟僮鲾?shù)當(dāng)成十進(jìn)制數(shù)(而不 是規(guī)格說(shuō)明中要求的十六進(jìn)制數(shù))的情況,第三個(gè)測(cè)試用例證實(shí)了這種假設(shè),程序 并未顯示 32 個(gè)字節(jié)的內(nèi)存單元的內(nèi)容,而僅顯示了 16 個(gè)字節(jié),這與我們的假設(shè)是 一致的,即“11”被當(dāng)作了十進(jìn)制數(shù)。因此,提煉后的假設(shè)是,程序?qū)⒆止?jié)數(shù)當(dāng)作 內(nèi)存地址處理,并將輸出列表中的內(nèi)存地址當(dāng)作十進(jìn)制數(shù)。最后的步驟是證明該假 設(shè)??匆豢吹谒膫€(gè)測(cè)試用例,如果 8000 被解讀為十進(jìn)制數(shù),則對(duì)應(yīng)的十六進(jìn)制數(shù) 是 1F40 ,這樣就會(huì)產(chǎn)生我們所看到的輸出。作為進(jìn)一步的證據(jù),檢查第二個(gè)測(cè)試 測(cè)試用例。輸出是不正確的,但如果 21 和 29 被當(dāng)作十進(jìn)制數(shù),那么內(nèi)存地址 15 ID 中的內(nèi)容將被顯示出來(lái),這是與測(cè)試用例的錯(cuò)誤結(jié)果是一致的。因此,我們幾 乎可以確切地定位錯(cuò)誤了:程序認(rèn)為操作數(shù)是十進(jìn)制數(shù),并將內(nèi)存地址按十進(jìn)制的 值打印出來(lái),這與規(guī)格說(shuō)明是不符的。而且,這個(gè)錯(cuò)誤似乎是造成所有四個(gè)測(cè)試用 例產(chǎn)生錯(cuò)誤結(jié)果的原因。經(jīng)過(guò)一些思考,我們發(fā)現(xiàn)了這個(gè)錯(cuò)誤,同時(shí)也解決了其他 三個(gè)乍看起來(lái)毫不相關(guān)的問(wèn)題。注意,該錯(cuò)誤可能在程序中的兩個(gè)地方顯現(xiàn)出來(lái):解釋輸入命令的部分和在輸出列表上打印內(nèi)存地址的部分。說(shuō)句離題的話,這個(gè)可能由于錯(cuò)誤理解規(guī)格說(shuō)明而引起的錯(cuò)誤進(jìn)一步印證了我 們的建議,即程序員不應(yīng)該測(cè)試自己編寫的程序。如果程序員在犯了這個(gè)錯(cuò)誤之后 仍然去設(shè)計(jì)測(cè)試用例,很有可能在編寫測(cè)試用例時(shí)犯同樣的錯(cuò)誤。換句話說(shuō),程序 員預(yù)料的輸出將不同于圖 7-5 所示的;這些輸出將是按操作數(shù)是十進(jìn)制數(shù)的理解而 被計(jì)算出來(lái)的,因此這個(gè)基本的錯(cuò)誤可能不會(huì)被察覺(jué)到。7.4 回溯法調(diào)試(Debugging by Backtracking)在小型程序中定位錯(cuò)誤的一種有效方法是沿著程序的邏輯結(jié)構(gòu)回溯不正確的 結(jié)果,直到找出程序邏輯出錯(cuò)的位置。換句話說(shuō),從程序產(chǎn)生不正確結(jié)果(如打印 了不正確的數(shù)據(jù))的地方開(kāi)始,從該處觀察到的結(jié)果推斷出程序變量應(yīng)該是些什么 值。在頭腦中,從這個(gè)位置開(kāi)始逆向執(zhí)行程序,重復(fù)使用“如果程序在此處的狀態(tài) 是這樣的,那么程序在上面位置的狀態(tài)就必然是那樣的”過(guò)程,就能很快定位出錯(cuò) 誤。使用這個(gè)過(guò)程,可以確定程序中從狀態(tài)符合預(yù)期值的位置點(diǎn),到第一個(gè)狀態(tài)不 符合預(yù)期值的位置點(diǎn)之間的范圍。7.5 測(cè)試法調(diào)試(Debugging by Testing)最后一個(gè)“思維型”的調(diào)試方法是使用測(cè)試用例。這可能聽(tīng)起來(lái)有些奇怪,因 為從本章一開(kāi)始就將調(diào)試和測(cè)試區(qū)分了開(kāi)來(lái)。然而,考慮下面兩種類型的測(cè)試用例。 供測(cè)試的測(cè)試用例,其目的是暴露出以前尚未發(fā)現(xiàn)的錯(cuò)誤供調(diào)試的測(cè)試用例,其 目的是提供有用的信息,供定位某個(gè)被懷疑的錯(cuò)誤之用。兩者之間的區(qū)別是,供測(cè) 試的測(cè)試用例會(huì)“胖”一些,因?yàn)槲覀儽M量使用較少數(shù)量的測(cè)試用例來(lái)涵蓋較多的 條件,而供調(diào)試的測(cè)試用例則“瘦”一些,因?yàn)槊總€(gè)測(cè)試用例僅需要覆蓋一個(gè)或幾 個(gè)條件。換句話說(shuō),當(dāng)發(fā)現(xiàn)了某個(gè)被懷疑的錯(cuò)誤的癥狀之后,我們需要編寫與原先有所 變化的測(cè)試用例,盡量確定錯(cuò)誤的位置。實(shí)際上,這種方法不是一個(gè)完全獨(dú)立的方 法;它常常結(jié)合歸納法一起使用,以獲得進(jìn)行假設(shè)和/或證明假設(shè)所需的信息。它也 可以和演繹法一起使用,以排除有嫌疑的原因,提煉剩下的假設(shè),并/或證明假設(shè)。7.6 調(diào)試的原則在本節(jié)中,我們將討論一系列的調(diào)試原則,在實(shí)質(zhì)上也是心理學(xué)的原則。與第2 章的測(cè)試原則情況一樣,這些調(diào)試原則有很多在直觀上很明顯,但卻常常被遺忘 或忽略。由于調(diào)試的過(guò)程由兩部分組成,即定位錯(cuò)誤及修改錯(cuò)誤,因此我們也將討 論兩類原則,7.6.1 定位錯(cuò)誤的原則1.動(dòng)腦筋 前面的章節(jié)隱含指出,調(diào)試是一個(gè)解決問(wèn)題的過(guò)程。最為有效的調(diào)試方法是動(dòng)腦筋對(duì)錯(cuò)誤癥狀的有關(guān)信息進(jìn)行分析。一個(gè)高效的程序調(diào)試人員應(yīng)該不使用計(jì)算機(jī)就能定位大多數(shù)的錯(cuò)誤。2.如果遇到了僵局,就留到稍后解決 人類的潛意識(shí)是一個(gè)潛在的問(wèn)題求解器。我們經(jīng)常提到的所謂靈感,其實(shí)就是當(dāng)人類的意識(shí)停留在諸如吃東西、走路或看電影之上時(shí),潛意識(shí)卻正在思考另一個(gè)向題。如果在合理時(shí)間內(nèi)(也許小型程序?yàn)?30 分鐘,大一點(diǎn)的程序?yàn)?幾個(gè)小時(shí)),我們還不能定位某個(gè)間題,就丟開(kāi)它,做些其他的事情,因?yàn)樗季S 的效率開(kāi)始明顯下降。忘記這個(gè)問(wèn)題一段時(shí)間之后,我們的潛意識(shí)可能已經(jīng)解 決了它,或者思維會(huì)煥然一新,可以重新檢查問(wèn)題的癥狀。3.如果遇到了困境,就把問(wèn)題描述給其他人聽(tīng) 與其他人交談可能會(huì)幫助我們發(fā)現(xiàn)一些新的東西。事實(shí)上,經(jīng)常是僅僅將問(wèn)題描述給一個(gè)好的傾聽(tīng)者時(shí),我們就會(huì)突然找到問(wèn)題的解決之道,而無(wú)需傾聽(tīng)者提供任何幫助。4.僅將測(cè)試工具作為第二種手段 在試過(guò)了其他的方法之后才使用調(diào)試上具,并將其作為頭腦思考的輔助手段,而不是替代手段。正如本章前面所述,調(diào)試工具比如輸出和跟蹤工具,代表的是一種偶然的調(diào)試方法。經(jīng)驗(yàn)證明,不使用工具的人即使在調(diào)試并不熟悉的程序時(shí),也要比使用工具的人更為成功。5.避免使用試驗(yàn)法僅將其作為最后的手段 調(diào)試程序的新手最常犯的錯(cuò)誤是為了解決問(wèn)題而試驗(yàn)性地去修改程序。調(diào)試者可能會(huì)說(shuō):“我知道什么出錯(cuò)了,所以我要改動(dòng)一下語(yǔ)句看一看會(huì)發(fā)生什么”。這種純粹是無(wú)計(jì)劃的方法甚至不屬于調(diào)試它表現(xiàn)的是盲目的行動(dòng)。它獲 得成功的機(jī)會(huì)不僅很小,而且還會(huì)將新的錯(cuò)誤引入程序,使問(wèn)題更為復(fù)雜。7.6.2 修改錯(cuò)誤的技術(shù)1.存在一個(gè)缺陷的地方,很有可能還存在其他缺陷這是對(duì)本書(shū)第 2 章原則的重申,即發(fā)現(xiàn)程序某個(gè)部分存在一個(gè)錯(cuò)誤時(shí),該 部分存在其他錯(cuò)誤的可能性要高于沒(méi)有發(fā)現(xiàn)錯(cuò)誤時(shí)的可能性。換句話說(shuō),錯(cuò)誤 有扎堆的傾向。在修改某個(gè)問(wèn)題的同時(shí),應(yīng)檢查下緊臨的地方,看看有沒(méi)有任 何可能是錯(cuò)誤之處。2.應(yīng)糾正錯(cuò)誤本身,而不僅是其癥狀 另一個(gè)普遍的錯(cuò)誤做法是只修改了錯(cuò)誤的癥狀或僅僅是該錯(cuò)誤的一個(gè)實(shí)例,而不是錯(cuò)誤本身。如果所做的改正不符合錯(cuò)誤的所有線索,那么可能只修改了錯(cuò)誤的一部分。3.正確糾正錯(cuò)誤的可能性并非 100%如果將這個(gè)觀點(diǎn)告訴一些人,他們當(dāng)然會(huì)表示贊同,但是如果將它說(shuō)給正 在修改錯(cuò)誤的人聽(tīng),答案就可能不一樣了(“是的,對(duì)大多數(shù)情況是這樣,但這 個(gè)修改如此之小,它肯定百分之百地正確”)。我們永遠(yuǎn)也不要假設(shè)為糾正錯(cuò)誤 而增加到程序中的代碼是正確的。用新的語(yǔ)句替換原來(lái)的語(yǔ)句,這種修改要遠(yuǎn) 比程序中原先的代碼更易發(fā)生錯(cuò)誤。言外之意是應(yīng)對(duì)錯(cuò)誤的修改進(jìn)行測(cè)試,也 許比對(duì)原先程序的測(cè)試還要嚴(yán)格。一個(gè)嚴(yán)格的回歸測(cè)試計(jì)劃可以確保對(duì)某個(gè)錯(cuò) 誤的修改沒(méi)有在程序的其他位置引入另外的錯(cuò)誤。4.正確修改錯(cuò)誤的可能性隨著程序規(guī)模的增加而降低換句話說(shuō),根據(jù)我們的經(jīng)驗(yàn),由于修改不正確而引人的錯(cuò)誤與原始錯(cuò)誤之比,在規(guī)模較大的程序中呈遞增趨勢(shì)。對(duì)于一個(gè)廣泛使用的大型程序,每發(fā)現(xiàn)6 個(gè)新錯(cuò)誤,其中就有 l 個(gè)錯(cuò)誤是由干先前對(duì)程序的改正而造成的。5.應(yīng)意識(shí)改正錯(cuò)誤會(huì)引入新錯(cuò)誤的可能性 我們不僅需要考慮到不正確的修改,而且還必須考慮到某個(gè)看似正確的修改會(huì)產(chǎn)生未料到的副作用,比如引入了一個(gè)新錯(cuò)誤。不僅存在修改無(wú)效的可能,還存在修改引入了新錯(cuò)誤的可能。言外之意是,不僅應(yīng)在修改之后對(duì)錯(cuò)誤的情 境進(jìn)行測(cè)試,還應(yīng)執(zhí)行回歸測(cè)試以判斷是否引入了新錯(cuò)誤。6.修改錯(cuò)誤的過(guò)程也是臨時(shí)回到設(shè)計(jì)階段的過(guò)程 我們應(yīng)該認(rèn)識(shí)到修改錯(cuò)誤也是程序設(shè)計(jì)的一種形式。在認(rèn)識(shí)到修改易產(chǎn)生錯(cuò)誤的性質(zhì)之后,常識(shí)告訴我們,在設(shè)計(jì)階段使用的任何規(guī)程、方法和形式都同樣適用于錯(cuò)誤修改階段。舉例來(lái)說(shuō),如果項(xiàng)目證明代碼檢查很管用,那么在 修改錯(cuò)誤之后進(jìn)行代碼檢查就顯得倍加重要。7.應(yīng)修改源代碼,而不是目標(biāo)代碼 在調(diào)試大型系統(tǒng),尤其是用匯編語(yǔ)言編寫的系統(tǒng)時(shí),偶爾會(huì)存在這樣的修改錯(cuò)誤的傾向,即先立即修改目標(biāo)代碼稍后再修改源程序這種方法帶來(lái)了兩個(gè)問(wèn)題,(1)這通常是“通過(guò)試驗(yàn)進(jìn)行調(diào)試”的信號(hào);(2)目標(biāo)代碼與源程 序不同步,這意味著當(dāng)程序重新編譯或重新匯編之后,同樣的錯(cuò)誤很容易又浮 現(xiàn)出來(lái),這是一種草率的、不專業(yè)的調(diào)試方法。7
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 航空航天復(fù)合材料 課件知識(shí)點(diǎn)6 高熵合金基復(fù)合材料
- 會(huì)滾的汽車課件
- 剪輯技巧培訓(xùn)課件
- 腫瘤科常用藥物臨床應(yīng)用與管理
- 路基工程這知識(shí)培訓(xùn)
- 2025年 安康市紫陽(yáng)縣民歌藝術(shù)研究中心招聘考試筆試試卷附答案
- 2025年中國(guó)噴泉套件行業(yè)市場(chǎng)全景分析及前景機(jī)遇研判報(bào)告
- 小動(dòng)物搬家課件
- 蛛網(wǎng)膜下腔出血疑難病例討論
- 紅血絲皮膚的成因及護(hù)理
- 大模型備案-落實(shí)算法安全主體責(zé)任基本情況-XX集團(tuán)有限公司
- 護(hù)理禮儀與人際溝通試題(含答案)
- 2025-2030中國(guó)蔬菜溫室大棚市場(chǎng)消費(fèi)趨勢(shì)分析與經(jīng)營(yíng)管理風(fēng)險(xiǎn)報(bào)告
- 學(xué)校外來(lái)人員登記制度
- 應(yīng)急物資中轉(zhuǎn)站項(xiàng)目可行性研究報(bào)告(模板范文)
- 2025年初級(jí)等保測(cè)評(píng)試題及答案
- 薄壁空心墩施工方案
- 多重耐藥菌醫(yī)院感染預(yù)防與控制技術(shù)指南(試行)
- 教師如何使用AI開(kāi)展教學(xué)DeepSeek使用指南人工智能 課件
- 油氣田地面工程詳解
- 地面注漿施工方案
評(píng)論
0/150
提交評(píng)論