这是另一篇关于我继承了一个 Intraweb 应用程序的帖子,该应用程序有一个 2MB 的内存泄漏文本文件,由 FastMM4 报告,我将其归结为一个类的 115 个实例,每个实例泄漏 52 个字节。
泄漏来自类的相当复杂的实例化和处理。需要类的每个实例化才能使应用程序立即工作。所以我正在寻找一些方法来克隆类,或者直接清理克隆,或者以不同的方式引用,或者..?
类(TCwcBasicAdapter)的第一个实例化是一个局部变量,它被添加到 TObjectList(不是 Owning)中,并与 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(不是 Owning)并与 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(Adapter) 行中的观察者模式的一部分。观察者被添加到 TObjectList FObservers (Owning):
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 中的私有字段,但这会导致错误。
谢谢,
保罗·赖斯