集計を使用して複数の子オブジェクトを含むクラスTParent
を作成したいとします。オブジェクトの中には独立しているものもあれば、他の子供たちに依存しているものもあります。すべての子オブジェクトは、親への参照を持たなければなりません。私はまた可能な限りインターフェイスを使いたいと思っています。Delphi:[weak]属性を使用したオブジェクトの集約とメモリリーク
私はTParent
の場合はTInterfacedObject
、子供の場合はTAggregatedObject
を使用しています。子供と親の両親がお互いに知っているので、私は循環の依存を避けるために弱い参照を使用しています。実際、この動作は既にTAggregatedObject
で定義されています。独立した子オブジェクト(TIndependantChild
)のみを使用している場合は、すべて正常に動作します。
子オブジェクトが他の子にも依存する場合、問題が発生します。コンストラクタTDependantChild
を参照してください。私は[weak]
アトリビュートでマークされているfChild変数に別の子オブジェクトへの参照を格納し、Delphi 10 Berlinで導入しました。 FastMM4は、シャットダウン時にメモリリークを報告します。
またSystem.TMonitor.Destroy
昇給につながる違反にアクセスしますが、FastMM4は用途にあり、ReportMemoryLeaksOnShutDownがTrueの場合にのみ、これは起こります。
program Project1;
{$APPTYPE CONSOLE}
uses
FastMM4,
System.SysUtils;
type
IParent = interface
['{B11AF925-C62A-4998-855B-268937EF30FB}']
end;
IChild = interface
['{15C19A4E-3FF2-4639-8957-F28F0F44F8B4}']
end;
TIndependantChild = class(TAggregatedObject, IChild)
end;
TDependantChild = class(TAggregatedObject, IChild)
private
[weak] fChild: IChild;
public
constructor Create(const Controller: IInterface; const AChild: IChild); reintroduce;
end;
TParent = class(TInterfacedObject, IParent)
private
fIndependantChild: TIndependantChild;
fDependantChild: TDependantChild;
public
constructor Create;
destructor Destroy; override;
end;
{ TParent }
constructor TParent.Create;
begin
fIndependantChild := TIndependantChild.Create(Self);
fDependantChild := TDependantChild.Create(Self, fIndependantChild);
end;
destructor TParent.Destroy;
begin
fDependantChild.Free;
fIndependantChild.Free;
inherited;
end;
{ TDependantChild }
constructor TDependantChild.Create(const Controller: IInterface; const AChild: IChild);
begin
inherited Create(Controller);
fChild := AChild;
end;
var
Owner: IParent;
begin
ReportMemoryLeaksOnShutDown := True;
Owner := TParent.Create;
Owner := nil;
end.
Iは、[危険]の代わりに[弱]を使用して問題を解決することが、見出されたが、デルファイに係るhelp
それ([危険])のみシステムユニットの外部で使用されるべきです非常にまれな状況です。
したがって、私は確信していません。私は[unsafe]
をここで使用する必要があります。特に何が起こっているのかわからないときは。
このような状況でのメモリリークの根拠とその克服方法を教えてください。
子供はなぜ集計する必要がありますか?集約が実際に何であるか理解していますか?なぜオブジェクト参照とインターフェイスを混在させるのですか?それは常に災害のレシピです。デバッガを使用して、メモリが漏れている理由を確認します。 –
10.1 Berlinのインタフェースに '[weak]'が追加されましたが、 '[weak]'は以前のバージョンに存在します。私はあなたのコードをそのままXE2でコンパイルできますが、 '[weak]'は効果がありません。 'Owner 'は、' TDependantChild'が '[weak]'であるにもかかわらず' fChild'が割り当てられているとき(集約のために) 'TParent'への非弱参照を持っているので' RefCount = 1'を持ちます。 'Owner'が破壊されると、' TInterfacedObject.BeforeDestruction() 'は' RefCount <> 0'のときにエラーを発生させ、 'Owner'とその子をリークさせます。 'fChild'を' Pointer'に変更するとそれが修正されます。あなたが ''安全でない ''を使用している場合、私はあなたの場合に似ていると思われます。デバッガで確認 –
レミー、コメントありがとうございます。私はそれが間違っていると理解していたかもしれませんが、集約コンセプトには新しいものです。私の場合、子オブジェクトは特定のクラス機能を表します。彼らは親なしでは意味がありませんが、同じ子オブジェクトを使って異なる親を構成することができます。私はインターフェイスとオブジェクトリファレンスを混在させたくないのですが、いくつかの例が見つかりました。[link](https://stackoverflow.com/questions/3483680/delphi-how-delegate-interface-implementation-to-child -object)、インターフェイスのみを使用するとエラーが発生しました。私はすぐに第二委員会をチェックします。 – VyPu