2009-06-27 79 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);