释放 TObjectList 时发生访问冲突

发布于 2024-11-29 13:44:03 字数 958 浏览 3 评论 0原文

我有以下德尔福代码:

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;

模块“Vcl50.bpl”中地址 4003AB4 处发生访问冲突。读取地址2980BFFC

我知道访问冲突通常是由于释放某些对象而导致的

  1. 之前已被释放,
  2. ,该对象在使用某些对象而未初始化

但是在我进行释放之前,我检查了分配已分配。如果我放弃异常处理,我的应用程序将抛出错误。 Allocations 是一个 TObjectList,如果它是一个数组 - 我会怀疑我没有为数组分配长度,但它是一个 TObjectList。

多谢!

I have the following Delphi code:

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;

Access violation at address 4003AB4 in module 'Vcl50.bpl'. Read of address 2980BFFC

I know the access violation usually caused by

  1. free some object which has been freed before
  2. use some object without initialization

But here before I do the free, I checked Allocations is assigned. If I discard the exception handling, my application will throw a something is wrong error.
Allocations is a TObjectList, if it is an array - I will doubt I didn't assign a length to the array, but it is a TObjectList.

Thanks a lot!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

韵柒 2024-12-06 13:44:03

TObjectList 通常负责销毁其内容。在这种情况下不要释放您的对象。这将导致释放 TObjectList 时发生访问冲突,因为它会尝试再次释放所包含的对象。

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

constructor TObjectList.Create(AOwnsObjects: Boolean);

使用此属性来指定是否希望列表拥有其内容(意味着:当项目从列表中删除时,它会负责销毁该项目)列表或列表被销毁)或不。不带参数的构造函数(您可能使用过)将其设置为 true

您可能只需要一个类似 TList 的列表,但用于存储对象。如果是这种情况,请像这样创建列表:

Allocations:= TObjectList.Create(False);

但如果您想要自动销毁行为,则只需删除 for 循环即可。对象列表将销毁您的 TXX_ALOC 对象。

A TObjectList usually takes care of destroying its content. Don't free your objects in this case. This will lead to an access violation when freeing the TObjectList because it tries to free the contained objects again.

This behavior of the object list can be controlled in its constructor:

constructor TObjectList.Create(AOwnsObjects: Boolean);

Use this one to specify if you want the list to own its content (means: it takes care of destroying an item when it is removed from the list or the list is destroyed) or not. The constructor without parameter (which you probably used) sets this to true.

You probably just want a list like TList but for storing objects. If that's the case then create your list like this:

Allocations:= TObjectList.Create(False);

But if you want the auto-destruction behavior then just remove the for-loop. The object list will destroy your TXX_ALOC objects.

浅语花开 2024-12-06 13:44:03

一般来说,当清除列表时,您希望从头到尾循环,

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

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

Generally, when clearing lists you want to loop from end to start ie

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

but in case of TObjectList, if the list owns objects (which it does by default) you shouldn't free them before destroying the container as the list will do it for you. In the code above, if the list owns the objects then calling Delete also frees the object.

柠檬色的秋千 2024-12-06 13:44:03

有 2 个选项供您选择...

1) 如果您希望 Delphi 在从 ObjectList 中删除对象时自动释放对象,则创建 TObjectList 并将 aOwnsObjects 设置为 true。在你的析构函数中简单的 FreeAndNil 是 ObjectList 本身。然后,这将从列表中删除所有对象并自动释放它们。由于释放 ObjectList 将自动释放该列表中包含的对象,因此您的代码可能如下所示:

destructor TXX_XXXX.Destroy;
begin
  FreeAndNil( Allocations ); //
  inherited;
end;

2) 创建 TObjectList 并将 aOwnsObjects 设置为 False,在这种情况下,您必须自己负责释放列表中的对象。您的代码可能如下所示:

destructor TXX_XXXX.Destroy;
var
  i       : Integer;
  oObject : TObject;
begin
  if Assigned(Allocations) then
  begin
    for i:= Pred( Allocations.Count ) downto 0 do
    begin
      // Get a reference to the Object
      oObject := TXX_ALOC(Allocations.Items[i]);
      // Remove the object from the object list
      Allocations.Delete( i );
      // Free the Object
      FreeAndNil( oObject );
    end;
  end;

  FreeAndNil( Allocations );
  inherited;
end;

There are 2 options for your ...

1) Create the TObjectList wiht the aOwnsObjects set to true if you want Delphi to automatically free the objects when they get removed from the ObjectList. And in your Destructor simple FreeAndNil the ObjectList itself. This will then remove all objects from the list and free them automatically. Since freeing the ObjectList will automatically free the objects contained in that list, Your code could then look like :

destructor TXX_XXXX.Destroy;
begin
  FreeAndNil( Allocations ); //
  inherited;
end;

2) Create the TObjectList wiht the aOwnsObjects set to False, in which case you will have to take care of freeing the objects in the list yourself. Your code could then look something like this :

destructor TXX_XXXX.Destroy;
var
  i       : Integer;
  oObject : TObject;
begin
  if Assigned(Allocations) then
  begin
    for i:= Pred( Allocations.Count ) downto 0 do
    begin
      // Get a reference to the Object
      oObject := TXX_ALOC(Allocations.Items[i]);
      // Remove the object from the object list
      Allocations.Delete( i );
      // Free the Object
      FreeAndNil( oObject );
    end;
  end;

  FreeAndNil( Allocations );
  inherited;
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文