Delphi-如何释放属于2个(或更多)列表的对象

Delphi-如何释放属于2个(或更多)列表的对象,delphi,list,memory-management,Delphi,List,Memory Management,在我正在处理的项目中,存在多个TList对象包含同一个item对象的情况 本质上,有一个包含所有项目对象的主列表,然后是只包含所有项目子集的较小列表。但是,项目是相同的,不是副本 问题出现的地方是在销毁过程中。将释放主列表,从而释放所有项。主列表通过覆盖“notify”来释放项目,子列表覆盖“notify”事件,这样项目就不会第二次被释放——无论如何都会失败 但是,当使用FastMM4时,内存泄漏日志会将这些项列为泄漏内存 那么,如何释放属于2个或更多列表的对象呢 顺便说一下,这不是我的代码,我

在我正在处理的项目中,存在多个TList对象包含同一个item对象的情况

本质上,有一个包含所有项目对象的主列表,然后是只包含所有项目子集的较小列表。但是,项目是相同的,不是副本

问题出现的地方是在销毁过程中。将释放主列表,从而释放所有项。主列表通过覆盖“notify”来释放项目,子列表覆盖“notify”事件,这样项目就不会第二次被释放——无论如何都会失败

但是,当使用FastMM4时,内存泄漏日志会将这些项列为泄漏内存

那么,如何释放属于2个或更多列表的对象呢

顺便说一下,这不是我的代码,我只是在做一些简单的维护。如果可以的话,我想避免创建每个对象的克隆来放在单独的列表中,但是嘿,男人必须做男人必须做的事情:o)

谢谢

布尔吉

编辑

没关系,我一定是疯了。现在FastMM4不会将项目标记为泄漏。。。只有子列表,它们实际上是主列表的子类。 这里一定有什么我遗漏了。我将运行更多的测试,以更清楚地了解正在发生的事情


感谢您迄今为止的所有回复。

我已经6年多没有写过任何Delphi了,但总的来说,我认为您希望这样做:

  • 正如您所说,主列表在其自身被释放时释放所有项
  • 子列表不会尝试释放项,因为它们是通过销毁主列表释放的。相反,他们只是从自己的清单中删除该项目,知道销毁工作正在其他地方进行

这相当简洁,但我认为它概括了您想要的一般模式。

我已经6年多没有写过任何Delphi了,但总的来说,我认为您希望这样做:

  • 正如您所说,主列表在其自身被释放时释放所有项
  • 子列表不会尝试释放项,因为它们是通过销毁主列表释放的。相反,他们只是从自己的清单中删除该项目,知道销毁工作正在其他地方进行

这相当简洁,但我认为它概括了您想要的一般模式。

为什么子列表覆盖notify事件?TList不会释放它所包含的项。或者你是在说TobjectList?
如果是TList,您确定这些项目确实已释放吗?有没有代码可以做到这一点?如果没有,它们不会被释放,fastmm是正确的:它们会泄漏。

为什么子列表会覆盖notify事件?TList不会释放它所包含的项。或者你是在说TobjectList?
如果是TList,您确定这些项目确实已释放吗?有没有代码可以做到这一点?否则,它们不会被释放,fastmm是正确的:它们会泄漏。

您可以尝试在Delphi中为接口使用自动引用计数机制。这样,对象将在清除最后一个引用后立即释放自己,而不必显式地释放它们。
为此,列表中包含的对象需要继承自TInterfacedObject并实现一些接口。

您可以尝试在Delphi中为接口使用自动引用计数机制。这样,对象将在清除最后一个引用后立即释放自己,而不必显式地释放它们。
要做到这一点,列表中包含的对象需要从TInterfacedObject继承并实现一些接口。

这是非常不够的,但可能不够效率并不是您的首要目标,所以我应该做的是对TList进行子类化,为这个列表创建一个特定的集合,它跟踪TSharedList的所有实例,并且,当一个列表中的一个项目被删除时,在所有其他列表中搜索并删除该项目

类似这样的内容(非线程安全):

单位共享列表;
界面
使用类;
类型
TSharedList=class(TList)
受保护的
过程通知(Ptr:Pointer;Action:TListNotification);推翻
平民的
构造函数创建;
毁灭者毁灭;推翻
终止
实施
变量
SharedListTracker:TList;
RecursiveCallFlag:布尔型;
过程TSharedList.Notify(Ptr:Pointer;Action:TListNotification);
变量
I:整数;
开始
如果是RecursiveCallFlag,则
出口
RecursiveCallFlag:=True;
尝试
如果Action=lnDeleted,则
对于I:=0到SharedListTracker.Count-1 do
如果(TSharedList(SharedListTracker[I])Self)和(TSharedList(SharedListTracker[I]).IndexOf(Ptr)-1),则
TSharedList(SharedListTracker[I]。删除(Ptr);
最后
RecursiveCallControl:=False;
终止
终止
构造函数TSharedList.Create;
开始
继承创造;
SharedListTracker.Add(Self);
终止
析构函数TSharedList.Destroy;
开始
SharedListTracker.Remove(自);
继承;
终止
初始化
SharedListTracker:=TList.Create;
定稿
SharedListTracker.Free;
终止

我很确定它不会编译(从未尝试过),但它显示了我的想法。

这是非常不充分的,但可能效率不是您在这里的第一个目标,所以我应该做的是对TList进行子分类,为这个列表创建一个特定的集合,它跟踪TSharedList的所有实例,并且,当一个列表中的一个项目被删除时,搜索所有其他列表并删除其中的项目

类似这样的内容(非线程安全):

单位共享列表;
界面
使用类;
类型
TSharedList=class(TList)
受保护的
过程通知(Ptr:Pointer;Action:TListNotification);重写;
平民的
构造函数创建;
析构函数销毁;重写;
终止
实施
变量
SharedListTracker:TList;
RecursiveCallFlag:布尔型;
过程TSharedList.Notify(Ptr:Pointer;Action:TListNotification);
变量
I:整数;
开始
如果记录
unit SharedLists;

interface
uses Classes;

type
  TSharedList = class(TList)
  protected
    procedure Notify(Ptr: Pointer; Action: TListNotification); override;
  public
    constructor Create;
    destructor Destroy; override;
  end;

implementation

var
  SharedListTracker: TList;
  RecursiveCallFlag: Boolean;

procedure TSharedList.Notify(Ptr: Pointer; Action: TListNotification);
var
  I: Integer;
begin
  if RecursiveCallFlag then
    Exit;
  RecursiveCallFlag := True;
  try
    if Action = lnDeleted then
      for I := 0 to SharedListTracker.Count - 1 do
        if (TSharedList(SharedListTracker[I]) <> Self) and (TSharedList(SharedListTracker[I]).IndexOf(Ptr) <> -1) then
          TSharedList(SharedListTracker[I].Remove(Ptr);
  finally
    RecursiveCallControl := False;
  end;
end;

constructor TSharedList.Create;
begin
  inherited Create;
  SharedListTracker.Add(Self);
end;

destructor TSharedList.Destroy;
begin
  SharedListTracker.Remove(Self);
  inherited;
end;

initialization
  SharedListTracker := TList.Create;
finalization
  SharedListTracker.Free;
end.