Access Violations
訪問沖突
A. 簡(jiǎn)介
B. 設(shè)計(jì)期間的AVs
a. 硬件原因
b. 軟件原因
c. 庫的錯(cuò)誤
d. 升級(jí)C++Builder
C. 運(yùn)行期間的AVs
a. 程序退出時(shí)發(fā)生AVs
b. 將你的指針設(shè)為空指針!
c. 使用IDE管理!
d. 在Form中使用caFree!
e. 隨機(jī)AVs(非退出)
D. 用戶提出的更多建議
簡(jiǎn)介
訪問沖突(AVs)是Windows編程時(shí)發(fā)生的最麻煩的錯(cuò)誤之一。盡管很難用一篇文章來解釋清楚所有可能導(dǎo)致AVs的原因,我將盡可能的解釋所有我所知道的原因。若您有本文中未提及的AVs的解決辦法,請(qǐng)Email給作者。您的經(jīng)驗(yàn)將加到本文中。
C++Builder中發(fā)生的AVs主要有兩種形式。設(shè)計(jì)期間的AVs和運(yùn)行期間的AVs。我們開始討論吧。
設(shè)計(jì)期間的AVs
設(shè)計(jì)期間的AVs最容易捕捉到,但靠您自己很難真正除掉它。它們通常產(chǎn)生于編譯時(shí)、Builder啟動(dòng)和關(guān)閉時(shí),或者幾乎是隨機(jī)的。讓我們先討論以下這些已知的原因。
硬件原因
某些顯卡、雙處理器主板、和聲音設(shè)備會(huì)導(dǎo)致C++Buider中的AVs。為什么?您機(jī)器中的每一塊板卡都帶有設(shè)備驅(qū)動(dòng)。由于制造商、Windows版本、你使用的C++Builder版本的不同而存在兼容問題,會(huì)導(dǎo)致AVs問題。解決這種情況的步驟如下:
o 總是使用您系統(tǒng)部件的最新驅(qū)動(dòng)程序。若您使用隨Windows所帶的驅(qū)動(dòng)程序的話,你應(yīng)從制造商那兒獲取最新的升級(jí)版本。
o 訪問Borland.Com和DejaNews.Com上的新聞組,查找關(guān)于您的硬件設(shè)備的主題。某些顯卡已知有兼容問題。您可能需要更換硬件。使用人所共知的穩(wěn)定且成熟的廠商提供的硬件是個(gè)好主意。Matrox就是個(gè)顯卡的好例子。
o 檢查您所安裝的設(shè)備之間有沒有沖突是個(gè)必須的步驟。
o 對(duì)一些古怪的顯卡驅(qū)動(dòng)程序來說,有時(shí)調(diào)低分辨率有助于穩(wěn)定。
o 若您使用雙處理器的話,確保兩個(gè)處理器的step revision相同,就是要用完全一樣的兩個(gè)芯片啦。
軟件原因
盡管Windows是Intel體系中使用最廣泛的操作系統(tǒng),但它的歷史是充滿BUG、不穩(wěn)定的。有許多方法能幫您擁有一個(gè)更穩(wěn)定的編程工作站。按以下步驟將幫你預(yù)防此類AVs的發(fā)生。
o 禁用裝有Internet Explorer (IE) 4.x或更高版本的Windows工作站上的Active Desktop。盡管這個(gè)功能可以讓您定制自己的桌面,但同時(shí)也導(dǎo)致許多應(yīng)用程序產(chǎn)生問題。
o 盡管Windows 9X更大眾化,NT4(NT5)提供了幾乎是所有Windows平臺(tái)中最穩(wěn)定的環(huán)境。我想強(qiáng)調(diào)這應(yīng)是C++Builder程序員選擇的環(huán)境。
o 確保安裝了最新的NT系統(tǒng)補(bǔ)丁(SPx),每次發(fā)布的補(bǔ)丁都讓您的NT系統(tǒng)變得更穩(wěn)定。
o 在升級(jí)了主要軟件包后,重新安裝最新的SPx。包括MS Office,IE,甚至是在C++Builder安裝后,某些SPx更新的文件經(jīng)常在安裝驅(qū)動(dòng)時(shí)被覆蓋。如果SPx提問是否用舊版本取代新版本時(shí),回答否。
o 我們的經(jīng)驗(yàn)是當(dāng)你發(fā)現(xiàn)新裝的系統(tǒng),經(jīng)過一段時(shí)間后開始出現(xiàn)越來越多的問題時(shí)(包括AVs),重裝系統(tǒng)可以解決絕大多數(shù)的問題,并可以提高系統(tǒng)的整體性能。這可能很費(fèi)時(shí),但絕對(duì)有效。
庫的錯(cuò)誤
安裝了新的庫和組件后,應(yīng)該跟蹤一下并看一看是否有對(duì)設(shè)計(jì)期間AVs的更正。若發(fā)生了新的AVs,你也許希望卸載最近安裝的組件。如果AVs也消失的話,尋求供應(yīng)商的支持。
同時(shí)應(yīng)對(duì)ReadME文件與安裝簡(jiǎn)介多加注意。如果你升級(jí)了一個(gè)庫,這也許需要你改變你的include目錄設(shè)置,甚至修改你的make文件,來使新舊版本沒有沖突。如果可能并且升級(jí)程序允許,你應(yīng)該總是先卸載舊版本后再升級(jí)。
升級(jí)C++Builder
我可以保證我不為Inprise工作,也沒有得到任何利益。我無法再強(qiáng)調(diào)使用C++Builder的新版本的重要意義。AVs的數(shù)量尤其是設(shè)計(jì)期間的AVs在我從CB3升級(jí)至CB4(現(xiàn)在已經(jīng)是CB5啦)后,大大減少了。同時(shí),性能得到提升,有更多可以使用的資源。若你要長跑的話,升級(jí)是很值得的。
運(yùn)行期間的AVs
盡管跟蹤是一場(chǎng)噩夢(mèng),運(yùn)行期間的AVs是可以解決的,它們通常不是C++ Builder中所描述的bugs。在我開始幫你解決你代碼中的疑難前,你必須讀過并了解設(shè)計(jì)期間的AVs訊息。本部分中的建議只對(duì)運(yùn)行期間的AVs起作用。尤其注意你的include目錄是否包含最新升級(jí)的庫,這往往是罪魁禍?zhǔn)住H绻@些都不能解決你的問題,再讓我們討論編程方面,應(yīng)該可以解決你的問題,讓你回到工作中去。
程序退出時(shí)發(fā)生AVs
如果你已經(jīng)見過你的程序退出時(shí),彈出的AVs對(duì)話框,那么恭喜你現(xiàn)在象分享了許多C++Builder程序員一樣(包括我)的挫折。這類AVs是最難跟蹤的。因?yàn)閐ebuger通常會(huì)把你引入深不可測(cè)的VCL內(nèi)部或干脆指向工程cpp文件的后括號(hào)。但不要害怕,下面的東西將幫你走過你的AV經(jīng)歷中最壞最壞的部分。
將你的指針設(shè)為空指針!
導(dǎo)致AV的一個(gè)最大的原因是嘗試刪除一個(gè)非法指針。發(fā)生的原因可能使用了一個(gè)沒有初始化的指針或試圖將東西刪除兩遍。如果你遵照如下指導(dǎo),可以減少50%的AVs在您的程序中發(fā)生。對(duì)所有的指針,均如下操作:
1. 聲明指針之后,將其設(shè)為NULL。沒有這么做的話,你不要立刻對(duì)這個(gè)指針使用new動(dòng)作。否則當(dāng)程序退出并執(zhí)行刪除動(dòng)作的話,指針的地址將變成無意義的。然后你就得到一個(gè)AV。
2. 刪除一個(gè)指針后,將其設(shè)為NULL。盡管delete動(dòng)作已將內(nèi)存清除,但它并沒有清除指針地址。如果后來又刪除一次指針的話,將導(dǎo)致一個(gè)AV。
記住刪除一個(gè)NULL空指針沒有錯(cuò),也不會(huì)帶來副作用。
使用IDE管理!
如果你創(chuàng)建了一個(gè)屬于(owned by)其他對(duì)象的對(duì)象,讓Owner來刪除這個(gè)對(duì)象。糊涂了?請(qǐng)?jiān)试S我舉個(gè)例子解釋。如果你動(dòng)態(tài)創(chuàng)建了一個(gè)panel對(duì)象,并在new方法中將它的Owner設(shè)為一個(gè)Form(Tpanel MyPanel=new Tpanel(this))。這樣當(dāng)Owner(Form)被刪除時(shí),他將嘗試刪除你的panel。如果你已經(jīng)刪除了…,哇,AV。所以,任何時(shí)候當(dāng)你new一個(gè)對(duì)象并在構(gòu)造函數(shù)(constructor)中設(shè)定了它的Owner,不要手工刪除此對(duì)象,讓Builder來做。若你必須這樣做,確保你將它設(shè)為NULL。
在Form中使用caFree!
如果可以,不要手工刪除動(dòng)態(tài)創(chuàng)建的form實(shí)例,而在其exit事件中使用caFree.盡管這樣做并不一定解決你的訪問沖突(AVs)問題,但你可以分離出此原因。因?yàn)锳V將發(fā)生在事件中而不是在程序退出時(shí)。
隨機(jī)AVs(非退出)
創(chuàng)建一個(gè)程序問題列表不僅要花很多時(shí)間,而且你所碰見的問題我很可能沒有包含在內(nèi)。但這里仍有很小一部分最常見的AV代碼問題:
o 嘗試訪問字符串長度以外的位置。例如:字符串是NULL空的(""),并且試圖訪問串的第一個(gè)字符myStr[1]。
o 引用一個(gè)空指針。可能的原因有:指針應(yīng)該new卻沒有new、指針在被訪問之前就已刪除、局部和全局指針同名,全局或局部指針一個(gè)new過,但另一個(gè)被訪問了。
用戶提出的更多建議
防止訪問空指針問題的一個(gè)辦法是在決定使用指針做任何事之前總是先檢查所有的指針。可以有許多方法來實(shí)現(xiàn)。最好的辦法恐怕是使用assert,其實(shí)if(myptr!=NULL) {...}的形式也不錯(cuò)。值得指出的是對(duì)多層指針(multi-level),if方法同樣可以很好的工作。這要感謝C語言堅(jiān)決支持在“if”謂詞的第一個(gè)假值處就跳轉(zhuǎn)(布爾賦值短路)。如:if(myptr!=NULL && myptr->itsptr!=NULL && myptr->itsptr->ptr2!=NULL) {....}
在下面的例子中int *pArray = new int[2];pArray[0] = 1; pArray[1] = 2; pArray[2] = 2; 溢出!! 數(shù)組只申請(qǐng)了8 bytes...并沒有彈出通常情況下的AV對(duì)話框(帶紅X的那個(gè))。而是彈出了一個(gè)不帶圖標(biāo)的對(duì)話框,同時(shí)也彈出了CPU窗口。所以,當(dāng)你看到類似的情況,就可以知道有數(shù)組溢出….
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注