【问题标题】:Delphi 3 Memory Allocation ProblemDelphi 3 内存分配问题
【发布时间】:2011-03-05 12:46:35
【问题描述】:

我一定错过了一些相当容易的事情吗?我正在尝试在 Delphi 3 应用程序中创建一个链表。

这是通过 ItemListItem 两个类实现的。 ItemList 在表单创建时被实例化。它在表单的生命周期内持续存在。每个 Item 对象都根据需要进行实例化。该表单有一个名为AddAcc 的函数。 AddAcc 通过表单控件之一的 on-change 事件调用。

在这个 on-change 事件期间会发生什么:

  1. AddAcc 被调用
  2. AddAcc 创建一个新的Item 对象
  3. AccAdd 调用 ItemList.AddItem 并通过引用传递 Item
  4. AddItemItem 对象放在列表的尾部

我已经测试过 AddItem 并且效果很好。我的问题是每次调用 *AddAcc* 时都会获得相同的内存位置。我尝试了不同的方法来创建一个新的 Item 对象。我使用了 New、GetMem (w/FillChar),并实例化了一个 Item 类型的局部变量。所有对 AddAcc 的调用都会获得相同的内存位置。

我已将 Item 对象直接(通过引用)传递给 AddItem,或者将指针传递给 Item 对象。

我认为在链接列表中对 Item 对象实例的引用(指针)将确保 Item 的内存位置得到维护。但是,一旦退出 AddAcc 类,它似乎就会被收集。

FUNCTION AddAcc;

Var

     accItem : ptrItem;

BEGIN

    GetMem(accItem, sizeOf(Item));

    FillChar(accItem^, sizeof(Item), 0);

    ItemList.AddItem(accItem^);

End;



Procedure TItemList.AddItem(Var newItem : TAccessoryItem);

begin
   Inc(_count);

   // add first item to the list            
    If (_count = 1) Then 
    begin       

          _fifoHead := @newItem;
          _tail := @newItem;
          newItem.Next   := @_tail;
          newItem.Previous := @_fifoHead;
          exit;

    end;

     _tail^.Next := @newItem;  
     newItem.Previous := _tail^;
     mewItem.Next := @_tail;
     _tail := @newItem;         
end;

非常感谢任何帮助。

【问题讨论】:

  • 请给我们一些代码。看到您的代码后,我们会告诉您其中有什么问题。
  • 请贴出调用 AddAcc 的代码、AddAcc 方法本身、声明 ListItem 对象的代码行以及初始化它的代码行。基本上,声明、初始化、AddAcc + 至少一个调用 AddAcc 的地方(以及调用它的方法中的所有代码,而不仅仅是调用它的代码行)
  • 我猜你正在传递一个包含指针的局部变量的地址。
  • @David 听起来确实如此。
  • 你能发布真正的代码吗,这甚至不是帕斯卡。函数有返回值。您能否包括ItemptrItem 的类型定义。

标签: delphi memory-management linked-list


【解决方案1】:

这是我如何编写一个链表:

type
  PItem = ^TItem;
  TItem = record
    Next: PItem;
    Data: Integer;
  end;

procedure Add(var First: PItem; Data: Integer);
var
  NewItem: PItem;
begin
  New(NewItem);
  NewItem.Next := First;
  NewItem.Data := Data;
  First := NewItem;
end;

...

var
  First: PItem;
begin
  First := nil;
  Add(First, 42);
  //etc.
end;

当您需要解除分配列表时,请执行以下操作:

var
  Item: PItem;
begin
  while Assigned(First) do begin
    Item := First;
    First := Item.Next;
    Dispose(Item);
  end;
end;

我相信这是用 Pascal 编写链表类型代码的规范方式。

我特意为这个可以想象的最简单的链表编写了这段代码。这使您可以专注于分配、指针的使用等。您似乎已经知道如何在更复杂的列表中维护引用,因此我相信您可以轻松地根据需要调整这种代码风格。

【讨论】:

  • 感谢大卫这有帮助。我简化了我的代码,使其更符合您提供的内容。在此过程中,我将 AddItem 和列表头尾指针移出 ItemList 并移到包含 AddAcc 的单元中。由于某种原因,这允许维护列表中每个节点的内存(不是垃圾收集)。今晚我将对此进行更全面的调查,并对我的发现发表评论……感谢您的帮助!
  • @mad moe,澄清一下:Delphi 不进行垃圾收集。你的代码很糟糕;您错误地调用了 AddItem(使用 accItem^,这是 accItem 的 content)而不是内存块的地址(accItem 本身 - 请注意缺少的取消引用运算符 ^),您错误地收到了它在 addItem 中使用 `var',这意味着您可以更改 address 以及内容,然后在 addItem 中错误地使用了 address-of (@) 运算符。 Delphi 不是 C# 或 VB.NET 或 Java。它不进行垃圾收集 - 您需要自己管理它。 :-)
  • @Ken 谢谢。我没有试图深入研究 OP 的代码,因为我觉得从头开始会更好。
  • 我同意你的选择,直到我点击 Moe 评论的“垃圾收集”部分;我想确保实际问题足够清楚以避免这种误解。
猜你喜欢
  • 2011-01-07
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
  • 2021-06-30
相关资源
最近更新 更多