2009-06-24 65 views
7

我用下面的檢查看一些代碼(德爾福7)是在每一個方法調用的頂部特定對象:爲什麼要檢查對象方法中的Assigned(self)?

if not Assigned(self) then 
    raise Exception.CreateRes(@sAbstractError); 

    { Real code for this method} 

我想,這將防止我試圖調用一個方法空對象指針。但是,無論如何,只要我試圖訪問成員數據,我就會得到一個異常,對吧?

這是我以前從未見過的這種標準嗎?有問題的對象來自TPersistent。

回答

8

你可以調用一個空指針的實例方法,儘管它不是你想要刻意去做的事情。當發生這種情況時,執行繼續非常愉快地進行,直到需要訪問實例數據,然後一切都會變得很快。

在這種情況下,檢查nil會在過程的頂部提醒您,以便您可以執行不同的操作,例如記錄堆棧跟蹤。或者你可以在投注線上設置一箇中斷點,這樣你就可以潛入並看到發生了什麼。

即,如果我有一個特定的錯誤,我試圖追蹤哪裏使用了零參考,我可能會這樣做。

經常這樣做會使我感到代碼味道。

4

存在訪問衝突情況,可能導致代碼在內存中運行,其中Self爲零。一些程序員,而不是解決真正的問題,試圖繞過使用這種斷言,以防止各種腐敗。我會很好地檢查這個異常是否會在運行時引發,如果是的話 - 你的手中有bug代碼。

您可以閱讀以下關於該主題的文章:When Self in Nil... You Know You are in Trouble

另一種可能性與事件有關,您可以在這裏閱讀更多內容,並提供大量此類測試的實例以及相應的解釋:Multicast Events - Part 2

+2

我不會說這個例子代碼繞過真正的問題。相反,它明確地強調了這個問題。 – 2009-06-25 00:29:50

10

一個明確的錯誤,抱怨一個零指針比沒有說出它發生的訪問衝突更好。

+1

+1用於捕獲零指針而不是*可能*訪問衝突。 – 2009-06-24 22:53:16

+0

那麼你是說你用這種方式編寫所有的對象嗎? – 2009-06-24 23:19:07

1

然後總是有這種可能性,在無零自我運行時代碼不會崩潰。示例 - 如果它未訪問所有者對象的任何字段。在這種情況下,這個測試將會發現原本不會被發現的問題。

不過,這是把防禦性編程帶到極致。我從來沒有(好吧,幾乎從來沒有 - 只有當我狩獵wabbits ...錯誤...壓扁錯誤)做到這一點。

1

似乎該方法的初衷是它成爲一種抽象方法。

3

這是一個肯定會導致崩潰(即操作系統例外,如「從地址0x00000000讀取」)的場合。拋出一個語言異常簡直是多餘的(並且濫用EAbstractError在這裏並沒有使它變得更好)。

檢查有效的輸入參數對於不安全的語言來說不是一個可行的任務,因爲你永遠不會獲得確定性,因此對無效參數的處理將永遠不會一致。 (爲什麼當一個零指針被傳遞時拋出一個異常,而不是0x00000001,這同樣是無效的?)。關於這個問題的更多技術性討論,請閱讀Larry Osterman的博客why not to check for valid pointers

應該注意一個例外:在Delphi中,可以在零指針上調用Free方法,這當然需要這種檢查。

相關問題