<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>
關(guān) 閉

新聞中心

EEPW首頁(yè) > 安全與國防 > 軟件故障的克星:斷言調試

軟件故障的克星:斷言調試

——
作者: 時(shí)間:2007-01-19 來(lái)源: 收藏

斷言(Assertive debugging)是利用自帶代碼對程序進(jìn)行監控并能確保嵌入式系統性能的新型方法。

是一門(mén)有待進(jìn)一步深入研究的“藝術(shù)”……最有效的調試技術(shù)是那些在程序本身基礎上設計并構建的技術(shù)?,F在,許多最優(yōu)秀程序員都利用近一半的程序對另一半程序進(jìn)行調試;而用于調試的這一半程序最終將完全被摒棄。出人意料的是,這最終竟也能提高生產(chǎn)效率。 —節選自Donald Knuth的《計算機編程藝術(shù)(The Art of Computer Programming)》。

正如Don Knuth所述,調試經(jīng)常被我們嚴重忽視,而我們也因此付出了慘重的代價(jià)。近半個(gè)世紀以來(lái),我們在調試領(lǐng)域取得的成就微乎其微,結果因程序而陷入困境的項目比比皆是。因調試而浪費的時(shí)間和資源,在商業(yè)項目中,成本可能高達數十億美元;在軍事項目中,損失的不僅是金錢(qián),甚至包括生命。這種現狀簡(jiǎn)直讓人無(wú)法忍受:我們必須探尋新的方法和途徑。本文就提出了這樣一種新方法。

本文提出的新型調試系統“斷言調試系統(ADS)”可以將調試由次要的“藝術(shù)形式”提升為現代工業(yè)流程。ADS雖然利用了既有的思想,即John von Neumann于1947年首先提出的“斷言”理論,但據我所知,ADS處理斷言的方式卻是Neumann或任何其他人從未提出的新方式:ADS更系統也更徹底地利用斷言,而不像其他工具只在程序員想到的時(shí)候才使用。為此,ADS將斷言由半個(gè)世紀以來(lái)一直漂浮不定且鮮有建樹(shù)的理論轉化為足以引領(lǐng)程序開(kāi)發(fā)革命的技術(shù)。與Knuth的論述不同,ADS并不摒棄那部分用于調試的程序,而是將其作為程序主體補充的文檔進(jìn)行保存,這樣,當程序需要修改時(shí)完全可以加以復用。

程序是主要的瓶頸

現在幾乎不可能找到完全不需要編程運算的科學(xué)或工程項目,同樣地,也很難找到不因程序原因而無(wú)法預期交付的。調試問(wèn)題對幾乎所有的項目都至關(guān)重要,而因軟件程序故障帶來(lái)教訓也足夠深刻:當客戶(hù)對產(chǎn)品不滿(mǎn)意時(shí),我們會(huì )喪失業(yè)務(wù);當產(chǎn)品遲遲無(wú)法推向市場(chǎng)時(shí),我們的銷(xiāo)售額會(huì )下降。隨著(zhù)我們在關(guān)鍵應用中越來(lái)越頻繁地使用計算機,我們的教訓也越來(lái)越慘重,這不僅關(guān)乎任務(wù)完成,甚至性命攸關(guān)。

在這些關(guān)鍵應用中,慎重地選擇調試方法并加以證明變得越來(lái)越重要,甚至成為法律需要。對于那些高度依賴(lài)調試的應用而言,一半程序完全用于調試已日益無(wú)法忍受。ADS方法在編程的同時(shí)就能直接觸及這些問(wèn)題:這有助于開(kāi)發(fā)人員縮短調試進(jìn)程并支持軟件對象的系統級和存檔級調試。本文極力主張采用該方法,這或許有助于防止陷入困境。

調試的現狀

調試發(fā)展歷程中最值得關(guān)注的是,現代調試技術(shù)居然與半個(gè)世紀前剛剛進(jìn)入現代計算時(shí)代時(shí)沒(méi)有太大區別。我們仍然讓故障程序運行至預測的關(guān)鍵點(diǎn),然后停止運行并查看關(guān)鍵變量的狀態(tài)。只要其中一個(gè)關(guān)鍵變量的值與預期的不同,我們就會(huì )努力分析為什么會(huì )造成這種結果。如果不知道什么地方出錯,我們會(huì )重復執行這個(gè)過(guò)程,在程序更早的地方停下來(lái)。經(jīng)過(guò)若干次反復,我們就能在充分接近程序故障的地方停下來(lái),結果發(fā)現,故障的原因是:我們忘了重置某個(gè)計數器或清空某段內存、從而使某些數據結構產(chǎn)生溢出或犯了其他6種經(jīng)典編程錯誤中的任意一種。

這就是上個(gè)世紀50年代中葉的軟件調試方法,至今仍在沿用。如果時(shí)間允許且客戶(hù)足夠耐心,那么該方法仍將繼續沿用下去,直至最終找到困擾的程序故障。但這種方法的缺點(diǎn)也很明顯:通常只適用于一些特定情形,調試需要的時(shí)間也無(wú)法預知,而且并不能幫助程序員更好地理解程序調試或找到類(lèi)似的程序故障。

什么是程序故障?

為了說(shuō)明哪些程序故障才是真正麻煩的程序故障,即ADS專(zhuān)注解決的問(wèn)題,這里簡(jiǎn)要地對軟件故障進(jìn)行了分類(lèi)并說(shuō)明了各類(lèi)故障的嚴重性。這種分類(lèi)本身并無(wú)任何新意,只是收集并組織了一些通用常識,然后以便于理解ADS的形式組織起來(lái)。這里,我們考慮的只是程序員產(chǎn)生的錯誤,而由硬件故障、操作員錯誤操作或其他不受程序員控制的條件引發(fā)的故障本身并不復雜,所以不在A(yíng)DS處理的故障之列。程序員錯誤包括:

1. 算法設計錯誤。程序員或其客戶(hù)錯誤理解了問(wèn)題,因此解決問(wèn)題的方法(即算法)即便完美無(wú)缺,也無(wú)法發(fā)揮效用。例如,程序員假定地球是個(gè)完美的球體,然后基于此計算人造地球衛星的軌道。他的錯誤本身與算法無(wú)關(guān),但與他或客戶(hù)對問(wèn)題的理解有關(guān)。

2. 程序設計錯誤。盡管程序員對問(wèn)題的理解及解決問(wèn)題的方法都正確,但是在為解決方案設計程序時(shí)犯了錯誤。例如,他沒(méi)有意識到計算機執行程序的時(shí)間比根據常規預測的時(shí)間更長(cháng)。該問(wèn)題與計算機相關(guān):反映了程序員的理解能力,不與任何特定的計算機或編程語(yǔ)言相關(guān),而與對通用計算的理解有關(guān)。

3. 程序實(shí)現錯誤。程序員在生成計算機執行的指令時(shí)出現錯誤。這類(lèi)錯誤中,有以下兩種變形:

a. 體系或語(yǔ)法錯誤。程序違背了程序開(kāi)發(fā)工具規定的準則,但這種錯誤僅被這些工具捕獲。
b. 獨立或邏輯錯誤。程序本身沒(méi)有錯誤,但無(wú)法運行結束或產(chǎn)生錯誤輸出。程序員要么犯了機械錯誤(如拼寫(xiě)錯誤),要么使用了不能被開(kāi)發(fā)系統捕獲的類(lèi)格式錯誤,要么更嚴重地在詳細程序設計中犯下了邏輯錯誤,如疏忽了緩存刷新或在數據區外進(jìn)行寫(xiě)操作(這時(shí),顯然程序開(kāi)發(fā)工具出現了故障。這雖然不是這位程序員的錯,卻是另一位程序員的失誤)。

類(lèi)型1與算法無(wú)關(guān):這些故障只是因為疏忽大意或愚鈍而產(chǎn)生,因此也無(wú)須采取任何特殊補救措施。類(lèi)型2與計算機相關(guān),但也不是太棘手:這些故障顯而易見(jiàn),一般程序設計早期階段就能發(fā)現,因此問(wèn)題也不是太突出。類(lèi)型3a現在已經(jīng)得到了很好的解決,大多數現代程序開(kāi)發(fā)系統能檢測出所有的通用語(yǔ)法錯誤并精確地定位。有時(shí),這些軟件甚至還能糾錯,例如一些專(zhuān)用于文字處理的程序就能自動(dòng)地將“hte”糾正為“the”。

真正危險的程序故障

類(lèi)型3b才是真正棘手的問(wèn)題:它的特點(diǎn)是容易引入、難以發(fā)現,通常直到出現最壞結果才顯露出來(lái)。這類(lèi)問(wèn)題之所以難以對付,完全是因為故障非?,嵥?、不引人注目,因此很難定位。類(lèi)型3b程序故障(以后簡(jiǎn)稱(chēng)為“程序故障”)確實(shí)非常危險,因為這類(lèi)故障很少立即表現出來(lái)。感染了這類(lèi)故障的程序通常情況下不會(huì )表現出任何癥狀,直到程序災難性崩潰或產(chǎn)生明顯錯誤的輸出才表現出來(lái)。這類(lèi)故障一般能使程序無(wú)故障地長(cháng)時(shí)間運行,直到實(shí)際影響結果。顯然,這時(shí)不僅程序出現了故障,而且大多數情況下,程序還將試圖刪除或破壞定位故障所需的信息;于是,我們又不得不重新開(kāi)始漫長(cháng)而艱辛的回退調試流程。

因此,我們需要的調試方法是希望通過(guò)某種途徑讓程序故障迅速自動(dòng)暴露出來(lái),這樣我們就能在第一時(shí)間意識到問(wèn)題存在并在程序破壞定位信息之前采取保護措施。理想情況下,我們希望程序故障甚至能在出現之前就自動(dòng)“跳出來(lái)”,也就是說(shuō),我們希望能在程序故障“干壞事”之前就一把抓住。這就是設計ADS的初衷。

ADS的工作原理

程序故障一出現即能立即捕獲的調試方法是通過(guò)在程序運行時(shí)監控眾多變量以找到那些違反程序員定義的斷言約束的故障。這里的“變量”并不單單指那些數學(xué)意義上的變量,還包括那些屬性以可預知方式改變的程序結構,而改變的方式可以是絕對改變,也可以是基于其他程序結構的相對改變。在這之中,還包括那些描述循環(huán)遍歷次數、緩存寫(xiě)入前能容納的字符個(gè)數、分支開(kāi)關(guān)能處理的狀態(tài)數目等的數字變量。這些變量共同定義了程序執行過(guò)程。ADS一個(gè)重要的前提是,如果變量不違反某項約束,程序故障將不會(huì )生效。如果系統地檢測出這些約束違反,那么每個(gè)程序故障都將在其一出現就發(fā)出警告,從而便于發(fā)現和理解。

在整個(gè)程序執行中對斷言進(jìn)行嚴格且系統的測試相當于在程序執行通道兩側建立起“防護墻”,這樣任何偏離通道的程序執行都將使運行的程序與某些斷言發(fā)生直接碰撞。因此,我們就能在每次執行失敗中找到一些有價(jià)值的東西:找到程序故障(至少顯著(zhù)縮小故障搜索范圍)或程序員的錯誤理解。

使用ADS

對于每個(gè)程序結構,程序員可以在變量定義的時(shí)候,就指定變量的約束條件??赡艿募s束條件如下所示,其他的約束條件可以在使用ADS過(guò)程中不斷擴充:

* 最大值和最小值;
* 變化的步長(cháng);
* 對于變量的取值,可以循環(huán)取值,還是只能使用一次,或是隨機取值;
* 該變量與其他一個(gè)或多個(gè)變量間的關(guān)系;
* 變量可取值或不可取值的顯式列表;
* 指針或鏈接變量所能指向的結構類(lèi)型;

這些斷言的表示方式是程序員使用的編程語(yǔ)言的自然延伸并可以幾種方式進(jìn)行歸類(lèi),因此,程序員可以通過(guò)一條命令使一組相關(guān)斷言生效或失效。

在主程序的每次編譯中,主程序代碼中激活的斷言可被用來(lái)檢驗其監控的變量,如變量值的每次改變,是否違反了任何約束條件等(“可被用來(lái)”的含義表示,并不是每次都需要執行每項測試)。當監控代碼檢測到任何變量已違反(或在某些情形下,即將違反)某個(gè)斷言,斷言將停止程序執行并運行程序員指定的異常處理程序。

這一點(diǎn)充分顯示了ADS調試方法與目前眾多程序員使用的斷點(diǎn)終止法的主要區別。ADS停止程序執行并不是因為程序執行到某個(gè)程序員希望在此通過(guò)檢查某些變量以獲取信息的點(diǎn)上;這個(gè)點(diǎn)或許遠比程序員預想插入的斷點(diǎn)提前或滯后,只要在這點(diǎn)上檢測到異常。此外,中止點(diǎn)與異常實(shí)際發(fā)生點(diǎn)非常接近。中止點(diǎn)的檢測也不受程序員的控制,當ADS報告該事件時(shí),與目前使用的斷點(diǎn)中止法所采用的隨機搜索機制不同,如果程序故障不馬上出現的話(huà),ADS用戶(hù)下一步可以返回程序并采取更大的監控力度以使所有代碼動(dòng)態(tài)地指示異常檢測,這樣就能盡早地捕獲程序故障。

遺憾的是,由于A(yíng)DS并未得到充分構建和使用,因此缺乏有效展示ADS有效性的方法,但我們可以借助一個(gè)并不具有結論性的假想試驗進(jìn)行說(shuō)明。根據最近解決的問(wèn)題或以往經(jīng)驗人為地構造一個(gè)實(shí)際的程序故障。在錯誤指令導致程序正常行為出現首次異常之前,要記錄下程序中的變量值,同時(shí)啟動(dòng)斷言檢測。請記住,如果采用了ADS,那么ADS將監控程序中的每個(gè)變量(即每個(gè)變化可預測的結構)的每次取值變化是否違反了當初設定的范圍。通過(guò)比較程序故障首次顯現與ADS停下來(lái)指示程序故障之間的間隔,就能深刻體會(huì )ADS在調試中帶來(lái)的便捷。在幾乎所有情形下,我們都能找到傳統調試方法與ADS調試方法的巨大區別,兩者完全不可同日而語(yǔ)。

斷言調試的成本

雖然大多數程序員都表示ADS能幫助他們更快地找出程序故障,但許多人仍堅持ADS的成本實(shí)在過(guò)于昂貴:實(shí)時(shí)檢測使ADS程序執行占用的系統資源是普通程序執行的數百倍。很多程序員一想到提供全部斷言檢測將使ADS嚴格地監控整個(gè)程序就覺(jué)得難以承受。這些擔心無(wú)疑是杞人憂(yōu)天,因為他們只看到了表面而沒(méi)有深入分析。

為了真正對ADS方法的成本進(jìn)行評估,首先需要明確的是,該方法比較的對象是實(shí)際應用的現有調試方法?,F有調試方法在查詢(xún)程序故障中給出的提示信息往往很少或者甚至沒(méi)有,因此,對于整個(gè)調試的成本,這部分成本也必須加以考慮。另一方面,采用ADS方法,每次程序執行都將得到有用的存檔信息:要么找到違反斷言約束之處,要么在運行到結束時(shí)報告程序完全無(wú)故障。即便ADS報告了斷言違反約束,而結果表明程序代碼完全正確,那么說(shuō)明程序員設定的斷言有誤,從而可以獲得一些有效信息。實(shí)際上,其中最有價(jià)值的并不是找到單個(gè)程序故障,而是找到程序員對程序的錯誤理解,這無(wú)疑更為重要。此外,需要注意的是,ADS的成本貫穿于整個(gè)產(chǎn)品周期,ADS節省的是項目預算時(shí)間、軟件工程師調試時(shí)間和產(chǎn)品的上市時(shí)間??偠灾?,ADS是通過(guò)犧牲那些成本幾乎可以忽略不計的低成本資源,實(shí)現節省高成本的資源的目標。

斷言在程序員聲明變量和數據結構就已明確表示,也就是說(shuō),當程序員在構造斷言時(shí)就已充分理解了該斷言?,F有的實(shí)現系統需要程序員對變量和結構進(jìn)行完整的靜態(tài)定義;而ADS只要求對變量或結構在程序實(shí)時(shí)運行中的允許取值或禁止取值添加顯式聲明。實(shí)際上,用戶(hù)在最理想的時(shí)間完成了大量的調試工作:他并不會(huì )迫于壓力在規定的時(shí)間內定位特定的程序故障,而且這時(shí)候他的頭腦最清晰,思維最敏銳。

基本原理比較

采用ADS工具與其他傳統工具的最大區別在于,只要預先加以定義,那么從定義開(kāi)始并在整個(gè)用戶(hù)設定的限制約束內,ADS將進(jìn)行完整的系統工作。在傳統調試方法中,系統只向用戶(hù)反饋這樣的信息:“我也不知道為什么程序會(huì )在這個(gè)點(diǎn)上停止下來(lái),或許你在這里設定了一個(gè)斷點(diǎn),因此這時(shí)候你可以在既有認知能力條件下,通過(guò)一個(gè)窗口觀(guān)察任何一個(gè)可能與程序故障檢測相關(guān)的變量。如果程序當前狀態(tài)下存在異常,你將能識別該異常,但如果跳過(guò)某個(gè)變量,我將無(wú)法識別某些異常?!?

相反,ADS會(huì )這樣表示:“早在程序設計和開(kāi)發(fā)時(shí)期,你就告訴我,對于程序中眾多變量和結構中的任意一個(gè),那些情況屬于異常;接著(zhù),你又告訴我將跟蹤那些異常,我就會(huì )按照你的指示尋找程序異?!,F在,我找到一個(gè)異常并記錄下詳細信息,如下所示……”有了ADS,軟件工程師將完全從事設計規劃,而調試系統則完成大量的煩瑣工作。

上述兩種方法可以通過(guò)比較每個(gè)項目因軟件故障而導致的項目延遲以及能否使編程更高效可靠來(lái)區分。



關(guān)鍵詞: 調試 故障 軟件

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>