2013-12-22 44 views
1

我之前打開過一個類似的話題,但我沒有明確的理由,因爲在嘗試釋放類實例時,錯誤「無效指針操作」。現在我已經知道了原因,所以我開了一個新的話題,揭露了這個問題。失敗釋放接口實現類

所以這個錯誤的原因是,當實例化類ChatClient並作爲參數傳遞類本身的實例(TChatManager)。問題可能與TChatManager類到接口的實現有關。

接口:

Type 
    // An interface definition 
    IMessageEvents = Interface(IInterface) 
    ['{BD27EFC6-CC9A-437A-A8B8-16F722518836}'] 

    Procedure messageReceived(messageData: String); 
    End; 

類TChatManager:

Type 
    TChatManager = Class(TInterfacedObject, IMessageEvents) 
    Private 
    cChatClient: TChatClient; 
    Protected 
    Procedure messageReceived(messageData: String); Overload; 
    Public 
    Constructor Create; Overload; 
    Destructor Destroy; Override; 
    End; 

Implementation 

Constructor TChatManager.Create; 
Begin 
    Inherited Create; 
    self.cChatClient := TChatClient.Create(self); // self class instance as parameter 
End; 

Procedure TChatManager.messageReceived(messageData: String); 
Begin 

End; 

Destructor TChatManager.Destroy; 
Begin 
    Inherited Destroy; 
End; 

類TChatClient:

Type 
    TChatClient = Class(TObject) 
    Private 
    iMsgEvents: IMessageEvents; 
    Protected 
    Public 
    Constructor Create(iMsgEvents: IMessageEvents); Overload; 
    Destructor Destroy; Override; 
    End; 

Implementation 

Constructor TChatClient.Create(iMsgEvents: IMessageEvents); 
Begin 
    Inherited Create; 
    self.iMsgEvents := iMsgEvents; 
End; 

Destructor TChatClient.Destroy; 
Begin 
    Inherited Destroy; 
End; 

主營:

cChatManager: TChatManager; 
self.cChatManager := TChatManager.Create; 
self.cChatManager.Free; // Failed 

任何人都可以解釋我執行不好?謝謝。

注:的類是不完整的,我刪除了一些方法,其中釋放的對象,等...

問候。

+0

@LU RD謝謝你的迴應。類沒有完成,我刪除了釋放對象的方法。但問題不在那裏。 –

+0

@大衛,是的,我知道,事實上在第一行我已經說過我曾經發布過類似的問題。事實是,雖然問題解決了,但我不明白究竟是什麼導致錯誤發現,所以我不得不打開一個新的話題。 –

+2

我以爲我已經解釋過了。也許不夠好。關鍵是接口引用控制着生命週期。你必須停止保持引用而不是接口引用。 –

回答

4

回答你的問題是TInterfacedObject以下方法:

procedure TInterfacedObject.BeforeDestruction; 
begin 
    if RefCount <> 0 then 
    Error(reInvalidPtr); 
end; 

你的代碼被破壞,因爲它是由TChatClient實例引用具有非零RefCount領域TChatManager實例。


的OP代碼不能被固定,應該(通過設置iMsgEvents:= nil)在當前形式TChatManager情況下,應在TChatClient析構函數被破壞,因爲重新設計,這是奇怪! :)

+0

這就是引發異常的原因。真正的問題是通過分配給'TChatManager'類型的變量'cChatManager'引起的引用計數生命週期管理的顛覆。 –

+0

@ user246408謝謝,現在我明白爲什麼會出現這個錯誤。大衛也感謝你的迴應。 –

+2

@DavidHeffernan - 這是個好問題;確定混合對象和接口引用是不好的設計,但要發現錯誤本身是有趣的事情。 – kludg