對(duì)程序行逐條跟蹤_第1頁(yè)
對(duì)程序行逐條跟蹤_第2頁(yè)
對(duì)程序行逐條跟蹤_第3頁(yè)
已閱讀5頁(yè),還剩4頁(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)介

1、第 4 章 對(duì)程序進(jìn)行逐條跟蹤前面我們講過(guò), 發(fā)現(xiàn)程序中錯(cuò)誤的最好方法是執(zhí)行程序。 在程序執(zhí)行過(guò)程中, 通過(guò)我們 的眼睛或者利用斷言和子系統(tǒng)一致性檢查這些自動(dòng)的測(cè)試工具來(lái)發(fā)現(xiàn)錯(cuò)誤。 然而, 雖然斷言 和子系統(tǒng)檢查都很有用, 但是如果程序員事先沒(méi)有想到應(yīng)該對(duì)某些問(wèn)題進(jìn)行檢查也不能保證 程序不會(huì)遇到這些問(wèn)題。這就好比家庭安全檢查系統(tǒng)一樣。如果只在門和窗戶上安裝了警報(bào)線, 那么當(dāng)竊賊從天窗或地下室的入口進(jìn)入家中時(shí), 就 不會(huì)引起警報(bào)。 如果在錄像機(jī)、 立體聲音響或者其它一些竊賊可能盜取的物品上安裝了干擾 傳感器,而竊賊卻偷取了你的 Barry Manilow 組合音響,那么他很可能會(huì)不被發(fā)現(xiàn)地逃走。

2、 這就是許多安全檢查系統(tǒng)的通病。 因此, 唯一保證家中物品不被偷走的辦法是在竊賊有可能 光顧的期間內(nèi)呆在家里。防止錯(cuò)誤進(jìn)入程序的辦法也是這樣,在最有可能出現(xiàn)錯(cuò)誤的時(shí)候, 必須密切注視。那么什么時(shí)候錯(cuò)誤最有時(shí)能出現(xiàn)呢?是在編寫或修改程序的時(shí)候嗎?確實(shí)是這樣。 雖然 現(xiàn)在程序員都知道這一點(diǎn), 但他們卻并不總能認(rèn)識(shí)到這一點(diǎn)的重要性, 并不總能認(rèn)識(shí)到編寫 無(wú)錯(cuò)代碼的最好辦法是在編譯時(shí)對(duì)其進(jìn)行詳盡的測(cè)試。在這一章中, 我們不談為什么在編寫程序時(shí)對(duì)程序進(jìn)行測(cè)試非常重要, 只講在編寫程序 時(shí)對(duì)程序進(jìn)行有效測(cè)試的方法。增加對(duì)程序的置信最近, 我一直為 Microsoft 的內(nèi)部 Macintosh 開發(fā)系統(tǒng)編

3、寫某個(gè)功能。 但當(dāng)我對(duì)所編代 碼進(jìn)行測(cè)試時(shí), 發(fā)現(xiàn)了一個(gè)錯(cuò)誤。 經(jīng)過(guò)跟蹤, 確定這個(gè)錯(cuò)誤是出在另一個(gè)程序員新編的代碼 中。使我迷惑不解的是, 這部分代碼對(duì)其他程序員的所編代碼非常重要, 我想不出他這部分 代碼怎么還能工作。我來(lái)到他的辦公室,以問(wèn)究竟“我想,在你最近完成的代碼中我發(fā)現(xiàn)了一個(gè)錯(cuò)誤” 。我說(shuō)道?!澳隳艹榭湛匆幌聠??” 他把相應(yīng)的代碼裝入編輯程序, 我指給他看我認(rèn)為的問(wèn)題所在。 當(dāng)他看到那部分代碼時(shí)不禁 大吃一驚?!澳闶菍?duì)的,這部分代碼確實(shí)有錯(cuò)??墒俏业臏y(cè)試程序?yàn)槭裁礇](méi)有查出這個(gè)錯(cuò)誤呢?” 我也對(duì)此感到奇怪。 “你到底用什么方法測(cè)試的這部分代碼?” ,我問(wèn)道。 他向我解釋了他的測(cè)試方法

4、, 聽(tīng)起來(lái)似乎它應(yīng)該能夠查出這個(gè)錯(cuò)誤。 我們都感到很費(fèi)解。 “讓我們?cè)谠摵瘮?shù)上設(shè)置一個(gè)斷點(diǎn)對(duì)其進(jìn)行逐條跟蹤,看看實(shí)際的情況到底怎樣” ,我提議 道。我們給該函數(shù)設(shè)置了一個(gè)斷點(diǎn)。 但當(dāng)找們按下運(yùn)行鍵之后, 相應(yīng)的測(cè)試程序卻運(yùn)行結(jié)束 了,它根本就沒(méi)有碰上我們所設(shè)置的斷點(diǎn)。 沒(méi)過(guò)多久, 我們就發(fā)現(xiàn)了測(cè)試程序沒(méi)有執(zhí)行該函 數(shù)的原因在該函數(shù)所在調(diào)用鏈上幾層, 一個(gè)函數(shù)的優(yōu)化功能使這個(gè)函數(shù)在某種情況下面跳過(guò)了不必要的工作。讀者還記得我在第 1 章中所說(shuō)的黑箱測(cè)試問(wèn)題嗎?測(cè)試者給程序提供大量的輸入, 然后 通過(guò)檢查其對(duì)應(yīng)的輸出來(lái)判斷該程序是否有問(wèn)題。如果測(cè)試者認(rèn)為相應(yīng)的輸出結(jié)果沒(méi)有問(wèn) 題,那么相應(yīng)的程序就被

5、認(rèn)為沒(méi)有問(wèn)題。 但這種方法的問(wèn)題是除了提供輸入和接受輸出之外,測(cè)試者再?zèng)]有別的辦法可以發(fā)現(xiàn)程序中的問(wèn)題。上述程序員漏掉錯(cuò)誤的原因是他采用了黑箱方法對(duì)其代碼進(jìn)行測(cè)試,他給了一些輸入,得到了正確的輸出,就認(rèn)為該代碼是正確的。他沒(méi)有利用程序員可用的其他工具對(duì)其代碼進(jìn)行測(cè)試。同大多數(shù)的測(cè)試者不同,程序員可以在代碼中設(shè)置斷點(diǎn),一步一步地跟蹤代碼的運(yùn)行, 觀察輸入變?yōu)檩敵龅倪^(guò)程。盡管如此,但奇怪的是很少有程序員在進(jìn)行代碼測(cè)試時(shí)習(xí)慣于對(duì) 其代碼進(jìn)行逐條的跟蹤。許多程序員甚至不耐煩在代碼中設(shè)置一個(gè)斷點(diǎn),以確定相應(yīng)代碼是否被執(zhí)行到了。還是讓我們回到這一章開始所談?wù)摰膯?wèn)題上:捕捉錯(cuò)誤的最好辦法是在編寫或修改程序時(shí)

6、進(jìn)行相應(yīng)的檢查。那么,程序員測(cè)試其程序的最好辦法是什么呢?是對(duì)其進(jìn)行逐條的跟蹤, 對(duì)中間的結(jié)果進(jìn)行認(rèn)真的查看。對(duì)于能夠始終如一地編寫出沒(méi)有錯(cuò)誤程序的程序員,我并不認(rèn)識(shí)許多。但我所認(rèn)識(shí)的幾個(gè)全都有對(duì)其程序進(jìn)行逐條跟蹤的習(xí)慣。這就好比你在家時(shí)夜賊光臨了 除非此時(shí)你睡著了,否則就不會(huì)不知道麻煩來(lái)了。作為一個(gè)項(xiàng)目負(fù)責(zé)人,我總是教導(dǎo)許多程序員在進(jìn)行代碼測(cè)試時(shí),要對(duì)其代碼進(jìn)行遍查,而他們總是會(huì)吃驚地看著我。這倒不是他們不同意我的看法,而是因?yàn)檫M(jìn)行代碼遍查聽(tīng)起來(lái)太費(fèi)時(shí)間了。他們好容易才能趕得上進(jìn)度,又哪有時(shí)間對(duì)其代碼進(jìn)行逐條的跟蹤呢?幸好這 一直觀的感受是錯(cuò)誤的。是的,對(duì)代碼進(jìn)行逐條的跟蹤確實(shí)需要時(shí)間,但它

7、同編寫代碼相比,只是其一小部分。要知道,當(dāng)實(shí)現(xiàn)一個(gè)新函數(shù)時(shí),你必須為其設(shè)計(jì)出函數(shù)的外部界面,勾畫出相應(yīng)的算法并把源程序全部輸入到計(jì)算機(jī)中。與此相比,在你第一次運(yùn)行相應(yīng)的的程序時(shí),為其設(shè)置一個(gè)斷點(diǎn), 按下“步進(jìn)”鍵檢查每行的代碼又能多花多少時(shí)間呢?并不太多,尤其是在習(xí)慣成自然之后。 這就好比學(xué)習(xí)駕駛一輛手扳變速器的轎車,一開始好象不可能, 但練習(xí)了幾天以后,當(dāng)需要變速時(shí)你甚至可以無(wú)意識(shí)地將其完成。同樣,一旦逐條地跟蹤代碼成為習(xí)慣之后,我們也會(huì)不加思索地設(shè)置斷點(diǎn)并對(duì)整個(gè)過(guò)程進(jìn)行跟蹤??梢院茏匀坏赝瓿蛇@一過(guò)程,并最后檢查出錯(cuò)誤。代碼中的分支不要等到出了錯(cuò)誤再對(duì)程序進(jìn)行逐條的跟蹤當(dāng)然有些技術(shù)可以使我們

8、更加有效地對(duì)代碼進(jìn)行逐條的跟蹤。但是如果我們只對(duì)部分而不是全部的代碼進(jìn)行逐條跟蹤,那么也不會(huì)取得特別好的效果。例如,所有的程序員都知道錯(cuò)誤處理代碼常常有錯(cuò),其原因是這部分代碼極少被測(cè)試到,而且除非你專門對(duì)這部分代碼進(jìn)行測(cè)試,否則這些錯(cuò)誤就不會(huì)被發(fā)現(xiàn)。為了發(fā)現(xiàn)錯(cuò)誤處理程序中的錯(cuò)誤,我們可以建立使錯(cuò)誤情況發(fā)生的測(cè)試用例, 或者在對(duì)代碼進(jìn)行逐條跟蹤時(shí)可以對(duì)錯(cuò)誤的情況進(jìn)行模擬。后-種方法通常費(fèi)時(shí)較少。例如,考慮下面的代碼中斷:pbBlock = (byte*)malloc(32);if( pbBlock = NULL )處理相應(yīng)的錯(cuò)誤情況通常在逐條跟蹤這段代碼時(shí),malloc會(huì)分配一個(gè)32字節(jié)的內(nèi)存塊

9、,并返回一個(gè)非NULL的指針值使其中的錯(cuò)誤處理代碼被繞過(guò)。跟蹤這段代碼并在執(zhí)行完下行語(yǔ)句之后,但為了對(duì)該錯(cuò)誤處理代碼進(jìn)行測(cè)試, 可以再次逐條立即用跟蹤程序命令將 pbBlock置為NULL指針值:pbBlock =(byte*) malloc(32);雖然malloc可能分配成功,但將pbBlock置為NULL指針就相當(dāng)于 malloc產(chǎn)生了分配失敗,從而使我們可以步進(jìn)到相應(yīng)的錯(cuò)誤處理部分。(注意:在改變了 pbBlock的值之后,malloc剛分配的的內(nèi)存塊即被丟失,但不要忘了這只是在做測(cè)試!)除了要對(duì)錯(cuò)誤情況進(jìn)行逐條的跟蹤之外,對(duì)程序中每一條可能的路徑都應(yīng)該進(jìn)行逐條的跟蹤。程序中具有多條代

10、碼路徑的明顯情況是if和switch語(yǔ)句,但還有一些其它的情況: && |和?:運(yùn)算符,它們 每個(gè)都有兩條路徑。為了驗(yàn)證程序的正確性,至少要對(duì)程序中的每條指令逐條跟蹤一遍。在做完了這件事之后,我們對(duì)程序中不含錯(cuò)誤就有了更高的置信。至少我們知道對(duì)于某些輸入,相應(yīng)的程序肯 定沒(méi)錯(cuò)。如果測(cè)試用例選擇得好,代碼的逐條跟蹤會(huì)使我們受益非淺。對(duì)每一條代碼路徑進(jìn)行逐條的跟蹤 大的變動(dòng)過(guò)去程序員問(wèn)過(guò)這樣的問(wèn)題:“如果我增加的功能與許多地方的代碼都有關(guān)系怎么辦?那對(duì)所有增加的新代碼進(jìn)行逐條的跟蹤不是太費(fèi)時(shí)間了嗎?”假如你是這么想的,那么我不妨問(wèn)你另一個(gè)問(wèn)題:“如果你做了這么大的變動(dòng),在進(jìn)行這些改

11、動(dòng)時(shí)可能不引進(jìn)任何的問(wèn)題 嗎?“習(xí)慣于對(duì)代碼進(jìn)行逐條跟蹤會(huì)產(chǎn)生一個(gè)有趣的負(fù)反饋回路。例如,對(duì)代碼進(jìn)行逐條跟蹤的程序員很快就會(huì)學(xué)會(huì)編寫較小的容易測(cè)試的函數(shù),因?yàn)閷?duì)于大函數(shù)進(jìn)行逐條的跟蹤非常痛苦。(測(cè)試一個(gè)10頁(yè)長(zhǎng)的的函數(shù)比測(cè)試 10個(gè)一頁(yè)長(zhǎng)的函數(shù)要難得多)程序員還會(huì)花更多的 時(shí)間去考慮如何使必需做的大變動(dòng)局部化,以便能夠更容易地進(jìn)行相應(yīng)的測(cè)試。這些不正是我們所期望的嗎?沒(méi)有一個(gè)項(xiàng)目的負(fù)責(zé)人喜歡程序員做大的變動(dòng),它們會(huì)使整個(gè)項(xiàng)目太不穩(wěn)定。也沒(méi)有一個(gè)項(xiàng)目負(fù)責(zé)人喜歡大的、不好管理的函數(shù),因?yàn)樗鼈兂32缓镁S護(hù)。如果發(fā)現(xiàn)必須做大的變動(dòng), 那么要檢查相應(yīng)的改變并進(jìn)行判斷。同時(shí)要記住,在大多數(shù)情況下,對(duì)代碼進(jìn)

12、行逐條跟蹤所花的時(shí)間要比實(shí)現(xiàn)相應(yīng)代碼所花的時(shí)間少得多。數(shù)據(jù)流程序的命脈在我編寫的第 2 章中介紹的快速 memset 函數(shù)之前,該函數(shù)的形式如下(不含斷言)void* memset( void *pv, byte b, size _tsize )byte pb=(byte*)pv;if( size >= sizeThreshold )unsigned long l;/* 用 4 個(gè)字節(jié)拼成一個(gè)長(zhǎng)字 */l = (b<<24) | (b<<16) | (b<<8) | b;pb = (byte*)longfill( (long*)pb, 1, size/

13、4 );size = size 4;while( size- > 0 )*pb+ = b;return(pv);這段代碼看起來(lái)好象正確, 其實(shí)有個(gè)小錯(cuò)誤。 在我編完了上述代碼之后, 我把它用到了一個(gè)現(xiàn)成的應(yīng)用程序中, 結(jié)果沒(méi)有問(wèn)題, 該函數(shù)工作得很好。 但為了確信該函數(shù)確實(shí)起作用了,我在該函數(shù)上設(shè)置了一個(gè)斷點(diǎn)并重新運(yùn)行該應(yīng)用程序。在進(jìn)入代碼跟蹤程序得到了控制之后我檢查了該函數(shù)的參數(shù): 其指針參數(shù)值看起來(lái)沒(méi)問(wèn)題,大小參數(shù)亦如此, 字節(jié)參數(shù)值為零。這時(shí)我感到使用字節(jié)值 0 來(lái)測(cè)試這個(gè)函數(shù)真是太不應(yīng)該,因?yàn)樗刮液茈y觀察到許多類型的錯(cuò)誤,所以我立即把字節(jié)參數(shù)的值改成了比較奇怪的0x4E。我首先

14、測(cè)試了 size 小于 sizeThreshold 的情況,那條路徑?jīng)]有問(wèn)題。 隨后我測(cè)試了 size大于或等于 sizeThreshold 的情況, 本來(lái)我想也不會(huì)有什么問(wèn)題。 但當(dāng)我執(zhí)行了下條語(yǔ)句之后:l = (b<<24) | (b<<16) | (b<<8) | b;我發(fā)現(xiàn)I被置成了 0X00004E4E,而不是我所期望的值 Ox4E4E4E4E在對(duì)該函數(shù)進(jìn)行匯 編語(yǔ)言的快速轉(zhuǎn)儲(chǔ)之后, 我發(fā)現(xiàn)了這一錯(cuò)誤, 并且知道了為什么在有這個(gè)錯(cuò)誤的情況下該應(yīng) 用程序仍能工作。我用來(lái)編譯該函數(shù)的編譯程序?qū)⒄麛?shù)處理為16位。在整數(shù)為16位的情況下,b<<

15、24會(huì)產(chǎn)生什么樣的結(jié)果呢?結(jié)果會(huì)是0。同樣b<<16所產(chǎn)生的結(jié)果也會(huì)是 0。雖然這個(gè)程序在邏輯上并沒(méi)有什么錯(cuò)誤, 但其具體的實(shí)現(xiàn)卻是錯(cuò)的。 之所以該函數(shù)在相應(yīng)應(yīng)用程序中能夠工作, 是因?yàn)樵搼?yīng)用程序使用 memset來(lái)把內(nèi)存塊填寫為 0,而0<<24則仍是0,所以結(jié)果正確。我?guī)缀趿⒓淳桶l(fā)現(xiàn)了這個(gè)錯(cuò)誤, 因?yàn)樵诎阉鼣R置在一邊繼續(xù)往下走查之前, 我又多花了一點(diǎn)時(shí)間逐條跟蹤了這部分代碼。確實(shí),這個(gè)錯(cuò)誤很嚴(yán)重,最終一定會(huì)被發(fā)現(xiàn)。但要記住, 我們的目標(biāo)是盡可能早地查出錯(cuò)誤。對(duì)代碼進(jìn)行逐條跟蹤可以幫助我們達(dá)到這個(gè)目標(biāo)。對(duì)代碼進(jìn)行逐條跟蹤的真正作用是它可以使我們觀察到數(shù)據(jù)在函數(shù)中的流動(dòng)

16、。如果在對(duì)代碼進(jìn)行逐條跟蹤時(shí)密切地注視數(shù)據(jù)流,就會(huì)幫助你查出下面這么多的錯(cuò)誤:上溢和下溢錯(cuò)誤;數(shù)據(jù)轉(zhuǎn)換錯(cuò)誤;差1錯(cuò)誤;NULL指針錯(cuò)誤;使用廢料內(nèi)存單元錯(cuò)誤(0xA3類錯(cuò)誤);用=代替=的賦值錯(cuò)誤;運(yùn)算優(yōu)先級(jí)錯(cuò)誤;邏輯錯(cuò)誤。如果不注重?cái)?shù)據(jù)流,我們能發(fā)現(xiàn)所有這些錯(cuò)誤嗎?注重?cái)?shù)據(jù)流的價(jià)值在于它可以使你以另一種非常不同的觀點(diǎn)看待你的代碼。你也許沒(méi)能夠注意到下面程序中的賦值錯(cuò)誤:if( ch =''Expa ndTab();但當(dāng)你對(duì)其進(jìn)行逐條跟蹤,密切注視其數(shù)據(jù)流時(shí), 很容易就會(huì)發(fā)現(xiàn)ch的內(nèi)容被破壞了。為什么編譯當(dāng)序代碼進(jìn)行逐條跟發(fā)出警要密切注視數(shù)據(jù)流在我用來(lái)測(cè)試本書中程序的五個(gè)編譯程

17、序中盡管每個(gè)編譯程序的警告級(jí)別都被設(shè)置到最大,但仍沒(méi)有一個(gè)編譯程序?qū)τ?b<<24這個(gè)錯(cuò)誤發(fā)生警告。這一代碼雖然是合法的 ANSI C, 但我想象不出在什么情況下這一代碼實(shí)際能夠完成程序員的意圖。既然如此,為什么不給出警告呢?當(dāng)你遇到這種錯(cuò)誤,要告訴相應(yīng)編譯程序的制造商,以使該編譯程序的新版本可以對(duì)這 種錯(cuò)誤送出警告。不要低估作為一個(gè)花了錢的顧客你手中的權(quán)利。你遺漏了什么東西嗎?使用源級(jí)調(diào)試程序的一個(gè)問(wèn)題是在執(zhí)行一行代碼時(shí)可能會(huì)漏掉某些重要的細(xì)節(jié)。例如,假定在下面的代碼中錯(cuò)誤地將 &&輸入了 & :/*如果該符號(hào)存在并且它有對(duì)應(yīng)的正文名字,*那么就釋放這個(gè)名

18、字*/if( psym != NULL & psym->strName != NULL )FreeMemory( psym->strName );psym->strName = NULL;這段程序雖然合法但卻是錯(cuò)誤的。 if語(yǔ)句的使用目的是避免使用 NULL指針psym去引 用結(jié)構(gòu)symbol的成員strName,但上面的代碼做的卻并不是這件事情。相反,不管psym的值是否為NULL這段程序總會(huì)引用 strName域。如果使用源級(jí)調(diào)試程序?qū)Υa進(jìn)行逐條跟蹤,并在到達(dá)該if語(yǔ)句時(shí),按了“步進(jìn)” 鍵,那么調(diào)試程序?qū)颜麄€(gè) if語(yǔ)句當(dāng)做一個(gè)操作來(lái)執(zhí)行。如果發(fā)現(xiàn)了這個(gè)錯(cuò)誤,你

19、就會(huì)注意到 即使在其表達(dá)式的左邊是FALSE的情況下,表達(dá)式的右邊仍會(huì)被執(zhí)行。(或者,如果你很幸運(yùn),當(dāng)程序間接引用了 NULL指針時(shí)系統(tǒng)會(huì)出現(xiàn)錯(cuò)誤。 但并沒(méi)有許多的臺(tái)式計(jì)算機(jī)會(huì)這樣做, 至少在目前它們不這樣做。)記得我們以前說(shuō)過(guò):& 和?:運(yùn)算符都有兩條路徑,因此要查出錯(cuò)誤就必須對(duì)每條路徑進(jìn)行逐條的跟蹤。源級(jí)調(diào)試程序的問(wèn)題是用一個(gè)單步就越過(guò)了&&、|和?:的兩條路徑。有兩個(gè)實(shí)用的方法可以解決這一問(wèn)題。第一個(gè)方法,只要步進(jìn)到使用&&和|運(yùn)算符的復(fù)合條件語(yǔ)句,就掃描相應(yīng)的一些條 件,驗(yàn)證這些條件拼寫無(wú)誤然后使用調(diào)試程序命令顯示條件中每個(gè)比較的結(jié)果。這樣做可以

20、幫助我們查出在某些情況下雖然整個(gè)表達(dá)式的計(jì)算結(jié)果正確,但該表達(dá)式中確實(shí)有錯(cuò)誤這一情況。例如,如果你認(rèn)為在這種情況下|表達(dá)式的第一部分應(yīng)該是TRUE第二部分應(yīng)該是FALSE但其結(jié)果恰恰相反。此時(shí)雖然整個(gè)表達(dá)式的計(jì)算結(jié)果雖然正確,但表達(dá)式中卻有 錯(cuò)誤。觀察表達(dá)式的各個(gè)部分可以發(fā)現(xiàn)這類問(wèn)題。第二個(gè),也是更徹底的方法是在匯編語(yǔ)言級(jí)步進(jìn)到復(fù)合條件語(yǔ)句和?:運(yùn)算符的內(nèi)部。是的,這要花費(fèi)更多的工夫,但對(duì)于關(guān)鍵的代碼, 為了觀看到中間的計(jì)算結(jié)果而對(duì)其內(nèi)部的代碼實(shí)際地走上一遍是很重要的。這同對(duì)C語(yǔ)句進(jìn)行逐條的跟蹤一樣,一旦你習(xí)慣之后。對(duì)匯編語(yǔ)言指令進(jìn)行逐條地跟蹤也很快,只不過(guò)需要經(jīng)過(guò)練習(xí)而已。關(guān)掉優(yōu)化?源級(jí)調(diào)試

21、程序可能會(huì)隱瞞執(zhí)行的細(xì)節(jié)對(duì)關(guān)鍵部分的代碼要進(jìn)行匯編指令級(jí)的逐條跟蹤如果一有趣的練習(xí)。因?yàn)榫幾g程序在生成優(yōu)化的代碼時(shí),可能會(huì)把相鄰源語(yǔ)句對(duì)應(yīng)的機(jī)器代碼混在一塊。對(duì)于這種編譯程序,一條“單步”命令跳過(guò)三行代碼并非不常見(jiàn);同樣,利用“單步”指令 執(zhí)行完一行將數(shù)據(jù)從一處送到另一處的源語(yǔ)句之后卻發(fā)現(xiàn)相應(yīng)的數(shù)據(jù)尚未傳送過(guò)去的情況 也很常見(jiàn)。為了對(duì)代碼進(jìn)行逐條跟蹤容易一些, 在編譯調(diào)試版本時(shí)可以考慮關(guān)掉不必要的編譯程序 優(yōu)化。這些優(yōu)化除了擾亂所生成的機(jī)器代碼之外, 毫無(wú)用處。 我聽(tīng)到過(guò)某些程序員反對(duì)關(guān)掉 編譯程序的優(yōu)化功能他們認(rèn)為這會(huì)在程序的調(diào)試版本和交付版本之問(wèn)產(chǎn)生不必要的差別從 而帶來(lái)風(fēng)險(xiǎn)。 如果擔(dān)心編譯程序會(huì)產(chǎn)生代碼生成錯(cuò)誤的話, 這種觀點(diǎn)還有點(diǎn)道理。 但同時(shí)我 們還應(yīng)該想到, 我們建立調(diào)試版本的目的是要查出程序中的錯(cuò)誤, 既然如此, 如果關(guān)掉編譯 的優(yōu)化功能可以幫助我們做到這點(diǎn),那么就值得考慮。最好的辦法是對(duì)優(yōu)化過(guò)的代碼進(jìn)行逐條的跟蹤, 先看看這樣做的困難有多大, 然后為了 有效地對(duì)代碼進(jìn)行逐條跟蹤,只關(guān)閉那些你認(rèn)為必須關(guān)閉的編譯程序優(yōu)化功能。小結(jié)我希望我知道一種能夠說(shuō)服程序員對(duì)其代碼進(jìn)行逐條跟蹤的方法, 或者至少能夠使他們 嘗試一個(gè)月。但是我發(fā)現(xiàn),程序員一般說(shuō)來(lái)都克服不了“那太費(fèi)時(shí)間”這一想法。作為項(xiàng)目 負(fù)責(zé)人的一個(gè)好處是對(duì)

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論