2009-06-27 70 views
1

這是另一篇關於我繼承了一個IntraWeb應用程序,該應用程序有一個2MB的FastMM4報告的內存泄漏文本文件,其中我將它歸結爲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; 

的類的第二實例也作爲被添加到一個TObjectList(未擁有),並與TObjectList破壞局部變量(FAdapters):

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; 

的類的實例化第三是從TempMulticast.AddObserver觀察者模式的一部分(適配器)線abov即觀察員加入到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

如果列表不包含它們,它們所在的列表是如何銷燬的? – 2009-06-27 15:53:09

+0

FreeAndNil在其類的析構函數中的專用TObjectLists FCDSAdapters和FAdapter上調用。我放置了一些代碼,在FreeAndNil之前迭代調用每個TCwcBasicAdapter上的Remove,並且它們沒有任何區別,兩種方式都是TList.Delete。 – user122603 2009-06-28 12:47:28

回答

0

你意識到你可以自己不使他們的業主自動處理他們處置的對象?我問這個問題是因爲它感覺就像你試圖讓自動裝置在所有情況下都能做到這一點。

1

如果列表不是所有者,那麼當列表被釋放時,它們不會釋放對象。只是在每個項目上調用Remove都不會。您必須遍歷列表並在列表中的每個項目上調用Free,然後釋放列表本身。

如果您創建了列表所有者,那麼當您釋放列表時,他們會爲您執行此操作。

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