2013-12-16 80 views
1

我有一個小問題。正如標題所說我想釋放一個對象,其類實現一個接口,但是我得到一個錯誤「無效的指針操作」免費接口如何實現類?

我的接口:

Interface 

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

    Procedure messageReceived(messageData: String); 
    End; 

Implementation 

我的班級:

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

Implementation 

Constructor TChatManager.Create; 
Begin 
    { ....... } 
End; 

Procedure TChatManager.connect; 
Begin 
    { ....... } 
End; 

Procedure TChatManager.disconnect; 
Begin 
    { ....... } 
End; 

Procedure TChatManager.messageReceived(messageData: String); 
Begin 
    { ....... } 
End; 

Destructor TChatManager.Destroy; 
Begin 
    Inherited Destroy; 
End; 

我的代碼:

self.chatMng := TChatManager.Create; 
self.chatMng.Free; 

誰能告訴我什麼,我做錯了什麼?提前致謝。

+0

您將需要顯示一些使用顯示問題的界面的代碼。從目前爲止所顯示的情況來看,沒有什麼看起來不對,但妄言可能是一個雙重問題。 – afrazier

+0

@afrazier我沒有做任何特別的事情。我只是實例化對象,然後嘗試釋放它。顯然,這是一個雙重的免費問題,但並不是試圖在任何地方釋放對象。 –

+0

「chatMng」是什麼類型的變量? TChatManager或IMessageEvents? 「Self」的析構函數或者「OnDestroy」是否試圖釋放「chatMng」? – afrazier

回答

2

這樣看來,chatMngTChatManager類型。這可以通過您指定TChatManager.Create給它,並在其上調用Free的事實推導出。

然而,TChatManagerTInterfacedObject派生。這意味着它的生命週期是通過接口引用來控制的。當最終引用被釋放時,對象被銷燬。

經驗法則是,如果你從TInterfacedObject派生,那麼你絕不能採取比通過接口變量以外的對象的引用。

步驟來糾正你的代碼:

  1. 變化chatMngIMessageEvents類型。
  2. 取出呼叫chatMng.Free,編譯器會反對在任何情況下。
+0

感謝您的迴應,但我該如何做明確的銷燬對象? –

+1

對象在最終引用被釋放時被銷燬。所以,如果沒有其他的參考文獻存在,'chatMng:= nil'就可以做到這一點。通常你不明確銷燬引用計數的對象。 –

+0

我以爲接口引用計數只發生在處理接口變量時?也就是說,如果OP將對象傳遞給請求接口的東西,那麼它將增加refcount並在該東西中遞減爲零並釋放該對象。 – afrazier

1

他不能向我們展示所有代碼...因爲他顯示的內容不應該導致GPF ...您可以創建TInterfacedObject並釋放它...如果您沒有獲得對...但如果你得到一個參考,你是負責釋放它不再...

這裏的接口

unit Unit3; 



Interface 

uses 
    Classes, SysUtils; 

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

    Procedure messageReceived(messageData: String); 
    End; 



Type 
    TChatManager = Class(TInterfacedObject, IMessageEvents) 
    Private 
    FStrings: TStrings; 
    Protected 
    Procedure messageReceived(messageData: String); Overload; 
    procedure UpdateStatus(aString: string); 
    Public 
    Constructor Create(aStrings: TStrings); 
    Destructor Destroy; Override; 
    Procedure connect; 
    Procedure disconnect; 
    End; 

Implementation 

Constructor TChatManager.Create(aStrings: TStrings); 
Begin 
    { ....... } 
    FStrings := aStrings; 
    UpdateStatus('Created'); 
    Connect; 
End; 

Procedure TChatManager.connect; 
Begin 
    { ....... } 
    UpdateStatus('Connected'); 
End; 

Procedure TChatManager.disconnect; 
Begin 
    { ....... } 
    UpdateStatus('DisConnected'); 
End; 

Procedure TChatManager.messageReceived(messageData: String); 
Begin 
    { ....... } 
    UpdateStatus('Message Received'); 
    UpdateStatus(messageData); 
End; 

procedure TChatManager.UpdateStatus(aString: string); 
begin 
    FStrings.Add(aString); 
    FStrings.Add('RefCount: '+ IntToStr(Self.RefCount)); 
end; 

Destructor TChatManager.Destroy; 
Begin 
    Disconnect; 
    UpdateStatus('Destroyed'); 
    Inherited Destroy; 


End; 

end. 

這裏的形式

unit Unit2; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, unit3, StdCtrls; 

type 
    TForm2 = class(TForm) 
    Button1: TButton; 
    Memo1: TMemo; 
    Button2: TButton; 
    Button3: TButton; 
    Button4: TButton; 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
    procedure Button3Click(Sender: TObject); 
    procedure Button4Click(Sender: TObject); 
    private 
    { Private declarations } 
    chatMng: TChatManager; 
    iChatMng: IMessageEvents; 
    public 
    { Public declarations } 
    end; 

var 
    Form2: TForm2; 

implementation 

{$R *.dfm} 
type 
    THackManager= class(TChatManager); 

procedure TForm2.Button1Click(Sender: TObject); 
begin 
    chatMng := TChatManager.Create(Memo1.Lines); 
    THackManager(ChatMng).messageReceived('Hello World from Button1'); 
    chatMng.Free; 
end; 

procedure TForm2.Button2Click(Sender: TObject); 
begin 
    iChatMng := TChatManager.Create(Memo1.Lines); 
    iChatMng.messageReceived('Hello World from Button2'); 
    iChatMng := nil; 
end; 

procedure TForm2.Button3Click(Sender: TObject); 
begin 
    ChatMng := TChatManager.Create(Memo1.Lines); 
(ChatMng as IMessageEvents).messageReceived('Hello World from Button3'); 
//you can't call ChatMng...it's gone bye bye... 
//ChatMng.Free; //this will cause a GPF if you call free 
end; 

procedure TForm2.Button4Click(Sender: TObject); 
var 
    a_IChatMng: IMessageEvents; 
begin 

    ChatMng := TChatManager.Create(Memo1.Lines); 
    a_IChatMng := chatMng; 
(ChatMng as IMessageEvents).messageReceived('Hello World from Button4'); 
a_IChatMng.messageReceived('Hello World again from Button4'); 
//ChatMng.Free; //this will cause a GPF if you call free 
end; 

end. 

這是dfm

object Form2: TForm2 
    Left = 326 
    Top = 94 
    Caption = 'Form2' 
    ClientHeight = 292 
    ClientWidth = 581 
    Color = clBtnFace 
    Font.Charset = DEFAULT_CHARSET 
    Font.Color = clWindowText 
    Font.Height = -11 
    Font.Name = 'Tahoma' 
    Font.Style = [] 
    OldCreateOrder = False 
    PixelsPerInch = 96 
    TextHeight = 13 
    object Button1: TButton 
    Left = 40 
    Top = 200 
    Width = 75 
    Height = 25 
    Caption = 'Button1' 
    TabOrder = 0 
    OnClick = Button1Click 
    end 
    object Memo1: TMemo 
    Left = 40 
    Top = 32 
    Width = 411 
    Height = 129 
    TabOrder = 1 
    end 
    object Button2: TButton 
    Left = 160 
    Top = 200 
    Width = 75 
    Height = 25 
    Caption = 'Button2' 
    TabOrder = 2 
    OnClick = Button2Click 
    end 
    object Button3: TButton 
    Left = 272 
    Top = 200 
    Width = 75 
    Height = 25 
    Caption = 'Button3' 
    TabOrder = 3 
    OnClick = Button3Click 
    end 
    object Button4: TButton 
    Left = 376 
    Top = 200 
    Width = 75 
    Height = 25 
    Caption = 'Button4' 
    TabOrder = 4 
    OnClick = Button4Click 
    end 
end 
+0

上沾沾自喜。顯然沒有人寫道:self.chatMng:= TChatManager.Create; self.chatMng.Free;在一個接口引用之間進行。也只是因爲你沒有看到EInvalidPointer並不意味着其他人不會。取決於內存管理器和運氣。 –

+0

@David如果他們只是創造一個概念證明......就像我的代碼......它不是生產準備......但確實顯示事物如何工作的證明...... –

+0

我同意你的意見。很明顯,並不是所有的代碼都顯示出來了。省略是創建和自由之間的參考部分。 –