2011-01-13 28 views
7

我的應用程序由於不小心使用Delphi接口而導致另一個錯誤。當我將一個接口傳遞給忽略該參數的過程時,實例永遠不會被釋放。請看下面的簡單例子:未使用的接口引用不會被破壞

ITest = interface 
    procedure Test; 
end; 

Tester = class(TInterfacedObject, ITest) 
public 
    procedure Test; 
end; 

Base = class 
public 
    procedure UseTestOrNot(test : ITest); virtual; abstract; 
end; 

A = class(Base) 
public 
    procedure UseTestOrNot(test : ITest); override; 
end; 

B = class(Base) 
public 
    procedure UseTestOrNot(test : ITest); override; 
end; 

{ A } 

procedure A.UseTestOrNot(test: ITest); 
begin 
    test.Test(); 
end; 

{ B } 

procedure B.UseTestOrNot(test: ITest); 
begin 
    WriteLn('No test here'); 
end; 

// -------- Test --------------------------------------- 
var 
    list : TObjectList<Base>; 
    x : Base; 
    t : ITest; 
begin 
    ReportMemoryLeaksOnShutdown := true; 

    list := TObjectList<Base>.Create; 
    list.Add(A.Create); 
    list.Add(B.Create); 

    // 1 x Tester leak for each B in list: 
    for x in list do 
     x.UseTestOrNot(Tester.Create); 

    // this is ok 
    for x in list do 
    begin 
     t := Tester.Create; 
     x.UseTestOrNot(t); 
    end; 

    list.Free; 
end. 

你能解釋一下引用計數器出了什麼問題嗎? 你可以給任何最佳做法/指導方針(如「絕不在函數調用內創建一個接口實例[如果你不知道里面發生了什麼])

我能想到的這個例子的最佳解決方案是寫在Base類的模板方法,節省了通過測試的實例,並調用一個抽象DoUseTestOrNot方法。

編輯 德爾福2010

+0

什麼版本的Delphi是這樣的? – 2011-01-13 14:50:25

+1

對不起,這是德爾福2010 – hansmaad 2011-01-13 14:51:41

+0

無所謂,它是一個錯誤,無論版本。等到delphi ex 2?歡呼聲 – APZ28 2011-01-13 18:09:57

回答

8

這是一個不同的錯誤 here的表現形式。
我會將此添加到QC報告中。

這不會在Delphi XE更新1中重現。

- jeroen

8

添加一個GUID你ITEST聲明

ITest = interface 
['{DB6637F9-FAD3-4765-9EC1-0A374AAC7469}'] 
    procedure Test; 
end; 

循環改成這樣

for x in list do 
    x.UseTestOrNot(Tester.Create as ITest); 

GUID是neccesary能夠使用as

Test.Create as ITest使編譯器添加這些創建的對象超出範圍的釋放。