2017-02-17 19 views
9

Delphi Berlin 10.1 [weak](および[unsafe])参照を使用しているとき、 "Supports"関数と "QueryInterface" "weak"属性( "unsafe"属性と同じ動作)でマークされたインタフェース変数が与えられたときの参照カウント。Delphi "Supports"は[weak]または[unsafe]インターフェースの参照カウントをインクリメントします

program WeakReferences; 

{$APPTYPE CONSOLE} 

{$R *.res} 

uses System.SysUtils; 

type 
    IAnInterfacedObject = interface 
    ['{351DFDA3-42CA-4A1D-8488-494CA454FD9C}'] 
    end; 

    TAnInterfacedObject = class(TInterfacedObject, IAnInterfacedObject) 
    protected 

     function GetTheReferenceCount : integer; 

    public 
     constructor Create; 
     destructor Destroy; override; 
     property TheReferenceCount : integer read GetTheReferenceCount; 
    end; 

    constructor TAnInterfacedObject.Create; 

    begin 
     inherited Create; 
     writeln('(create AIO instance)'); 
    end; 

    destructor TAnInterfacedObject.Destroy; 

    begin 
     writeln('(destroy AIO instance)'); 

     inherited Destroy; 
    end; 

    function TAnInterfacedObject.GetTheReferenceCount : integer; 

    begin 
     Result := FRefCount; 
    end; 

    procedure WithoutSupports; 

    var 
     AIOinstance : TAnInterfacedObject; 

     AIOinterfaced : IAnInterfacedObject; 

     [Weak] 
     WeakAIOinterfaced : IAnInterfacedObject; 

    begin 
     AIOinstance := TAnInterfacedObject.Create; 
     writeln('created AIO instance; refcount: '+AIOinstance.TheReferenceCount.ToString); 

     AIOinterfaced := AIOinstance; 
     writeln('create AIO interfaced; refcount: '+AIOinstance.TheReferenceCount.ToString); 

     WeakAIOinterfaced := AIOinstance; 
     writeln('create WEAK AIO interfaced; refcount: '+AIOinstance.TheReferenceCount.ToString); 
    end; 

    procedure WithSupports_Weak; 

    var 
     AIOinstance : TAnInterfacedObject; 

     AIOinterfaced : IAnInterfacedObject; 

     [Weak] 
     WeakAIOinterfaced : IAnInterfacedObject; 

    begin 
     AIOinstance := TAnInterfacedObject.Create; 
     writeln('created AIO instance; refcount: '+AIOinstance.TheReferenceCount.ToString); 

     AIOinterfaced := AIOinstance; 
     writeln('create AIO interfaced; refcount: '+AIOinstance.TheReferenceCount.ToString); 

     Supports(AIOinstance, IAnInterfacedObject, WeakAIOinterfaced); 
     writeln('create WEAK AIO interfaced with SUPPORTS; refcount: '+AIOinstance.TheReferenceCount.ToString); 
    end; 

    procedure WithSupports_Unsafe; 

    var 
     AIOinstance : TAnInterfacedObject; 

     AIOinterfaced : IAnInterfacedObject; 

     [Unsafe] 
     UnsafeAIOinterfaced : IAnInterfacedObject; 

    begin 
     AIOinstance := TAnInterfacedObject.Create; 
     writeln('created AIO instance; refcount: '+AIOinstance.TheReferenceCount.ToString); 

     AIOinterfaced := AIOinstance; 
     writeln('create AIO interfaced; refcount: '+AIOinstance.TheReferenceCount.ToString); 

     Supports(AIOinstance, IAnInterfacedObject, UnsafeAIOinterfaced); 
     writeln('create UNSAFE AIO interfaced with SUPPORTS; refcount: '+AIOinstance.TheReferenceCount.ToString); 
    end; 

    procedure WithQueryInterface_Weak; 

    var 
     AIOinstance : TAnInterfacedObject; 

     AIOinterfaced : IAnInterfacedObject; 

     [Weak] 
     WeakAIOinterfaced : IAnInterfacedObject; 

    begin 
     AIOinstance := TAnInterfacedObject.Create; 
     writeln('created AIO instance; refcount: '+AIOinstance.TheReferenceCount.ToString); 

     AIOinterfaced := AIOinstance; 
     writeln('create AIO interfaced; refcount: '+AIOinstance.TheReferenceCount.ToString); 

     AIOinterfaced.QueryInterface(IAnInterfacedObject, WeakAIOinterfaced); 
     writeln('create WEAK AIO interfaced with QUERYINTERFACE; refcount: '+AIOinstance.TheReferenceCount.ToString); 
    end; 

begin 
    try 
    writeln('--Without "Supports"-------------------'); 
    WithoutSupports; 
    writeln; 
    writeln('--With "Supports" - weak-------------------'); 
    WithSupports_Weak; 
    writeln; 
    writeln('--With "Supports" - unsafe-------------------'); 
    WithSupports_Unsafe; 
    writeln; 
    writeln('--With "QueryInterface" - weak-------------------'); 
    WithQueryInterface_Weak; 

    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 

    readln; 
end. 

私はここで何を欠席しましたか? 「WeakSupports」機能はありますか?これはバグか、新しい「弱い」インターフェース機能の単なる欠点ですか?

答えて

6

デルファイSupports - 機能

function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; 

として

function Supports(const Instance: IInterface; const IID: TGUID; out Intf): Boolean; 

QueryInterfaceとして両方outパラメータは[weak]としてマークされていないと宣言された(オーバーロードの1が、他のすべては、同じ考慮outパラメータです) 。つまり、[weak]または[unsafe]のインターフェイス参照を渡すことはできません。このようなパラメータに強い参照を渡すだけで、参照カウントを順番に保持できます。ドキュメントWeak Referencesから

注:のみ、また、[弱]としてマークされたパラメータ VARやOUT [弱]変数を渡すことができます。通常の強い 参照を[弱い] varまたはoutパラメータに渡すことはできません。

注:[Unsafe]変数は、[安全でない]とマークされた変数 のvarまたはoutパラメータにのみ渡すことができます。通常の強力な リファレンスを[Unsafe] varまたはoutパラメータに渡すことはできません。


さらにテストケースは、別の問題があります。完全なARC Delphiコンパイラ(現在はAndroidとiOS)を使用している場合を除き、の参照カウントオブジェクトをオブジェクト参照に格納することはできません。より正確に言えば、非ARCコンパイラでのオブジェクト参照は参照カウントに寄与せず、宣言されたインタフェースからアクセスできないオブジェクトに対していくつかの操作を実行するための一時アクセスポイントとしてのみ使用できます。参照カウントを順番に保持し、オブジェクトの早すぎる破壊やメモリリークを防ぐためには、常にそのオブジェクトインスタンスへのインタフェース参照を少なくとも1つ持つ必要があります。

代わりの

var 
    AIOinstance : TAnInterfacedObject; 
    ... 
    AIOinstance := TAnInterfacedObject.Create; 

あなたは常に

var 
    AIOinstance : IAnInterfacedObject; 
    ... 
    AIOinstance := TAnInterfacedObject.Create; 
+0

を使用する必要があり、私は非ARCコードと混合するARCが難しい理由です...なぜ私はビジネスコードのためにARCに切り替えることはありません私はこれまでDelphiのLinuxコンパイラを使用することは疑問視しています。 –

+0

@ArnaudBouchez私はあなたが何を意味するか分かりません。オブジェクト参照とインタフェース参照の問題を混在させることは、ARCコンパイラが解決することとまったく同じです。もちろん、クロスプラットフォームコードでは、ARC以外のコンパイラルールに従い、それら2つを混ぜ合わせてはいけません。 –

+0

Dalija、ローカルオブジェクトインスタンスを持つオブジェクトを作成し、後でそれをインターフェイスに割り当てる有効な理由があります。オブジェクトを作成して初期化し、それをインタフェースに割り当てることがよくあります。 – Graymatter

関連する問題