释放TObjectList时访问冲突

sps*_*pli 4 delphi free access-violation

我有以下Delphi代码:

destructor TXX_XXXX.Destroy;
var
i: Integer;
begin
  if Assigned(Allocations) then
  begin
    for i:=0 to (Allocations.Count - 1) do 
    begin
      try
      TXX_ALOC(Allocations.Items[i]).Free;
      except on Ex:Exception do
      begin
        OutputDebugString(PChar('Exception Error Message '+ Ex.Message));
      end;
      end;
    end;

        // Above code works well - no exception

        try
    FreeAndNil(Allocations); {Exception Here}
    except on E:Exception do
    begin
      OutputDebugString(PChar('Exception in xxxxxxxxx.pas'+E.Message));
    end;
    end;
  end;
  inherited;
end;
Run Code Online (Sandbox Code Playgroud)

模块"Vcl50.bpl"中地址4003AB4处的访问冲突.读取地址2980BFFC

我知道通常由访问冲突引起的

  1. 释放一些以前被释放的物体
  2. 没有初始化就使用一些对象

但是在我免费之前,我检查了Allocations.如果我放弃异常处理,我的应用程序会抛出一些错误的错误.分配是一个TObjectList,如果它是一个数组 - 我会怀疑我没有给数组分配一个长度,但它是一个TObjectList.

非常感谢!

Hei*_*cht 18

一个TObjectList通常需要破坏其内容的照顾.在这种情况下,不要释放您的对象.这将在释放时导致访问冲突,TObjectList因为它试图再次释放包含的对象.

可以在其构造函数中控制对象列表的此行为:

constructor TObjectList.Create(AOwnsObjects: Boolean);
Run Code Online (Sandbox Code Playgroud)

使用此选项指定您是否希望列表拥有其内容(意味着:它会在从列表中删除项目时销毁项目或者列表被销毁).没有参数的构造函数(您可能使用过)将其设置为true.

您可能只需要一个列表,TList但用于存储对象.如果是这种情况,那么创建如下列表:

Allocations:= TObjectList.Create(False);
Run Code Online (Sandbox Code Playgroud)

但是如果你想要自动销毁行为,那么只需删除for循环.对象列表将破坏您的TXX_ALOC对象.


ain*_*ain 7

通常,清除列表时,您希望从头到尾循环,即

for i := (Allocations.Count - 1) downto 0 do begin
   Delete(Allocations.Items[i]);
end
Run Code Online (Sandbox Code Playgroud)

但是在TObjectList的情况下,如果列表拥有对象(默认情况下它),则在销毁容器之前不应释放它们,因为列表将为您执行此操作.在上面的代码中,如果列表拥有对象,则调用Delete也会释放该对象.