2011-08-16 85 views
3

我有以下代碼(我查objCur是不是免費前無}:這個無效指針在哪裏?

try 
    objCur.Free; 
Except on E:Exception do 
    begin 
    OutputDebugString(PChar('Exception '+E.Message)); 
    Assert(False); 
    end; 
end; 

據報告此異常消息:

無效的指針操作objCur是TXX_TEA型
objCur:TXX_TEA ;

在TXX_TEA.Destroy我有以下代碼

destructor TXX_TEA.Destroy; 
begin 
    OutputDebugString(PChar('Inside Destroy')); 
    ... 
    inherited; 
    OutputDebugString(PChar('End of Destroy')); 
end; 

在DebugView中我看到以下消息:

內摧毀
...
最終的銷燬

異常:無效的指針操作

我知道objCur.Free電話TXX_TEA.Destroy,但它看起來TXX_TEA.Destroy無誤地執行。那麼我應該在哪裏跟蹤這個無效的指針操作?

+3

檢查'objCur'是否爲非零是不夠的。事實上,如果它*爲零,你根本就沒有任何問題。你需要檢查它是否指向一個有效的對象,這實際上不是你可以通過編程來檢查的東西。您需要通過分析程序來檢查並確保您沒有任何會導致變量具有無效參考的錯誤。 –

+0

Acutally我想知道什麼時候objCur.Free,它會先調用TXX_TEA.Destroy,然後它將釋放它自身的屬性?因爲在TXX_TEA中,有一個屬性Allos,Allos [i] .xx = self.xx;在TXX_TEA.Destroy中,調用Allos.Free。所以我懷疑當objCur釋放它的xx屬性時,它已經被釋放了 – spspli

回答

9

當內存管理器被要求釋放不屬於它的內存時,會發生無效的指針操作。

對象的內存在最外面的析構函數返回給調用者之前被釋放。在這種情況下的來電者是TObject.Free。調用inherited不會導致釋放對象的內存,因爲編譯器知道它不是最外層的調用。顯然,你釋放了一個並不存在的對象,但是這個假定對象的內存內容看起來足夠有效,以至於清理對象字段的析構函數中的代碼不會崩潰。只有當析構函數完成運行並且對象將被釋放時,內存管理器纔會檢測到該地址沒有引用當前分配的任何內容。

3

很可能您仍然有一個對它的引用,並且某些代碼在釋放後使用該引用來訪問該對象。這可以是一個對象引用或接口引用(接口引用不爲零將在範圍末尾調用_Release)。

我們必須看到更多代碼才能真正找出導致它的原因。

+0

+1接口引用計數 –

+0

那麼是否有一個通用的方法來找出對象引用或接口引用的位置? – spspli

+1

使用RTL和VCL調試單元進行調試將幫助您瞭解實際發生的情況,以及可能出現的問題。在引發異常之前,還要查看堆棧跟蹤*。 –

6

一個無效的指針當你試圖釋放某些東西時的操作幾乎總是意味着它已經被釋放。如果你想找到哪裏,最簡單的方法是從SourceForge獲取完整版本的FastMM。閱讀文檔,它會告訴你如何將它添加到你的項目以及如何打開FullDebugMode。在FullDebugMode打開的情況下,當你試圖釋放已經釋放的東西時,它會通過一個對話框中斷程序,該對話框爲您提供了第一次釋放對象時的堆棧跟蹤。這應該有助於您追蹤錯誤。