2009-06-27 14 views
1

これは、FastMM4によって報告されたメモリリークの2MBのテキストファイルを持つIntrawebアプリケーションを継承した別の記事です。ここでは、1クラスの115インスタンスにそれぞれ52バイトのリークがあります。複数参照オブジェクトの解放

リークは、複雑なインスタンス化とクラスの処理からのものです。アプリをすぐに動作させるには、クラスの各インスタンス化が必要です。だから私は、クローンの単純なクリーンアップを使ってクラスをクローンするか、別の方法で参照するか、または..を参照するいくつかの方法を探しています。

クラス(TCwcBasicAdapter)の最初のインスタンスは、TObjectListを(所有せず)に加え、TObjectListを(FCDSAdapters)で破壊されますローカル変数の通りである:

procedure TCwcDeclaration.AttachAdapter(DS: TDataSource; const FormName, KeyFN, TitleFN: string; const Multiple: boolean = False; 
    const AllowAttachment: boolean = False; const AllowComment: boolean = False); 
var 
    Forms : TCwcSessionForms; 
    Adapter: TCwcCDSAdapter; 
    KeyField, TitleField: TField; 
begin 
    Forms := GetForms(FormName); 
    KeyField := DS.DataSet.FindField(KeyFN); 
    TitleField := DS.DataSet.FindField(TitleFN); 
    Adapter := TCwcBasicAdapter.Create(DS, KeyField, TitleField, Multiple); 
    Adapter.AttachDBPersist(Self.DBPersist); 
    Forms.AttachDataAdapter(Adapter); 
    Forms.SetAllowAttachments(AllowAttachment); 
    Forms.SetAllowComments(AllowComment); 
end; 

procedure TCwcSessionForms.AttachDataAdapter(aCDSAdapter: TCwcCDSAdapter); 
var 
    Index: integer; 
begin 
    if (FCDSAdapters.IndexOf(aCDSAdapter) -1) 
    then raise Exception.CreateFmt('Duplicate Adapter attempting to be attached on %0:s', [FFormClassName]); 
    Index := FCDSAdapters.Add(aCDSAdapter); 
    if (FDefaultAdapterIndex = -1) 
    then FDefaultAdapterIndex := Index; 
end; 

クラスの第二のインスタンスクラスの第三のインスタンスがTempMulticast.AddObserverからオブザーバーパターンの一部としてである

procedure TCwcCDSMulticastList.InitializeAdapters(const aSessionForms: TCwcSessionForms); 
var 
    i, Count: integer; 
    Adapter: TCwcCDSAdapter; 
    TempMulticast: TCwcCDSEventMulticast; 
begin 
    Count := aSessionForms.GetDataAdapterCount; 
    for i := 0 to Pred(Count) do begin 
     Adapter := aSessionForms.GetDataAdapter(i); 
     TempMulticast := FindDataSource(Adapter.DataSource); 
     if (TempMulticast = nil) then begin 
      TempMulticast := TCwcCDSEventMulticast.Create(Adapter.DataSource); 
      try 
      FMulticastList.Add(TempMulticast); 
      except 
      FreeAndNil(TempMulticast); 
      raise; 
      end; 
     end; 
     TempMulticast.AddObserver(Adapter); 
     FAdapters.Add(Adapter); 
    end; 
end; 

:TObjectListを(所有せず)に加え、TObjectListを(FAdapters)で破壊されますローカル変数としても(アダプタ)ラインabov e。オブザーバーは、(所有)TObjectListをFObserversに追加されます。

procedure TCwcCDSEventMulticast.AddObserver(const aCDSAdapter: TCwcCDSAdapter); 
begin 
    FObservers.Add(TCwcCDSAdapterObserver.Create(aCDSAdapter)); 
end; 

constructor TCwcCDSAdapterObserver.Create(const aCDSAdapter: TCwcCDSAdapter); 
begin 
    inherited Create; 
    FOnStateChange  := aCDSAdapter.OnStateChangeIntercept; 
    FOnAfterDelete  := aCDSAdapter.AfterDeleteIntercept; 
    FInvalidateCursors := aCDSAdapter.InvalidateCursors; 
end; 

TCwcBasicAdapterはFObserversが破壊されたときにクリーンアップされません、ここに漏洩しています。

私が試した最新のことはFObserversを所有していないものに変更して、アダプタのプライベートフィールドを作成し、TCwcCDSAdapterObserver.Destroyのプライベートフィールドを解放していますが、エラーが発生します。

おかげで、

ポール・ライス

+0

これらのオブジェクトは、リストが所有していない場合はどのように破壊されますか? –

+0

FreeAndNilは、クラスのデストラクタのプライベートTObjectLists FCDSAdapterおよびFAdapterで呼び出されます。私はいくつかのコードを繰り返し、FreeAndNilの前に各TCwcBasicAdapterでRemoveを呼び出すと、それは何の違いもありませんでした。どちらの方法もTList.Deleteを実行します。 – user122603

答えて

0

あなたはAUTO-処分それらの飼い主をせずに自分でオブジェクトを処分することができます実現?私はこれを尋ねます。なぜなら、すべてのケースで自動化を仕事にさせようとしているように感じるからです。

1

リストが所有者でない場合、リストが解放されたときにオブジェクトを解放しません。各項目でRemoveを呼び出すだけでは、それもできません。リストを繰り返し処理し、リスト内の各項目で「フリー」を呼び出してから、リスト自体を解放する必要があります。

リストの所有者を作成すると、リストを解放するときにこれを行います。

for i := 0 to FAdapters.Count do Free(FAdapters[i]); 
FreeAndNil(FAdapters); 
+1

こんにちは。多重参照オブジェクト。すべてのリストを所有することはできません。 ところで、上記の数は範囲外です。 – user122603

+1

はい、Count-1だったはずです。ありがとう。 いいえ、すべてのリストを所有者にする必要はありません。オブジェクトを解放したいものだけ。各オブジェクトには正確に1人の所有者が必要です。 オブジェクトを作成してローカル変数に割り当てる場合は、変数がスコープから外れる前にそのオブジェクトを解放するか、後で解放するオブジェクトに渡す必要があります。オブジェクトを作成し、所有者ではないと言うリストにそれらを渡しています。その場合、オブジェクトを所有するのは誰ですか?彼らはどこから解放されていますか? – TrespassersW

関連する問題