delphi3内存分配问题

delphi3内存分配问题,delphi,memory-management,linked-list,Delphi,Memory Management,Linked List,我一定错过了一些很容易的事情?我正在尝试在Delphi3应用程序中创建一个链表 这是通过两个类ItemList和Item实现的。ItemList在表单创建时实例化。它在形体的生命中持续存在。根据需要实例化每个Item对象。表单有一个名为AddAcc的函数。AddAcc是通过表单控件之一的on change事件调用的 此更改事件期间发生的情况: AddAcc被称为 AddAcc创建一个新的Item对象 AccAdd调用ItemList.AddItem并通过引用传递该项 AddItem将Item对象

我一定错过了一些很容易的事情?我正在尝试在Delphi3应用程序中创建一个链表

这是通过两个类ItemList和Item实现的。ItemList在表单创建时实例化。它在形体的生命中持续存在。根据需要实例化每个Item对象。表单有一个名为AddAcc的函数。AddAcc是通过表单控件之一的on change事件调用的

此更改事件期间发生的情况:

  • AddAcc被称为
  • AddAcc创建一个新的Item对象
  • AccAdd调用ItemList.AddItem并通过引用传递该项
  • AddItem将Item对象放置在列表的末尾
  • 我测试了AddItem,效果很好。我的问题是,每次调用*AddAcc*时,它都会获得相同的内存位置。我尝试了创建新项目对象的不同方法。我使用了New、GetMem(w/FillChar)和实例化Item类型的局部变量。对AddAcc的所有调用都会导致获得相同的内存位置

    我已经将Item对象直接(通过引用)传递给AddItem,或者传递一个指向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;
    

    非常感谢您的帮助。

    以下是我编写链接列表的方法:

    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编写链表类型代码的标准方法


    我特意为这个最简单的链表编写了这段代码。这使您能够将注意力集中在分配、指针的使用等方面。您似乎已经知道如何在更复杂的列表中维护引用,因此我相信您可以根据自己的需要调整这种代码样式。

    请给我们一些代码。一旦我们看到您的代码,我们将告诉您其中的错误。请发布调用AddAcc的代码、AddAcc方法本身、声明ListItem对象的代码行以及初始化它的代码行。基本上,声明、初始化、AddAcc+至少一个调用AddAcc的地方(以及调用它的方法中的所有代码,而不仅仅是调用它的代码行),我可以猜测您正在传递一个包含指针的局部变量的地址。@David听起来确实像。您能发布真正的代码吗,这甚至不是帕斯卡。函数有返回值。您能为
    项目
    ptrItem
    添加类型定义吗?谢谢David的帮助。我简化了代码,使之更符合您提供的内容。在这样做的过程中,我将AddItem和列表的头和尾指针从ItemList移到包含AddAcc的单元中。出于某种原因,这允许维护列表中每个节点的内存(而不是垃圾收集)。今晚我将对此进行更全面的调查,并对我的发现进行评论……我感谢您的帮助@mad moe,只是澄清一下:Delphi不做垃圾收集。你的代码很糟糕;您错误地调用了AddItem(使用accItem的内容)而不是内存块的地址(
    accItem
    本身-请注意缺少的取消引用运算符^),您错误地在带有“var”的AddItem中接收了它,这意味着您可以更改地址和内容,然后在addItem中错误地使用了(@)运算符的地址。Delphi不是C#或VB.NET或Java;它不进行垃圾收集-您需要自己管理它。:-)@肯,谢谢。我没有试图深入了解OP的代码,因为我觉得最好从头开始。我同意你的选择,直到我在Moe评论中提到“垃圾收集”部分;我想确保实际问题足够清楚,以避免这种误解。