4
votes

I must be missing something rather easy? I’m trying to create a linked list in a Delphi 3 application.

This is implemented via two classes ItemList and Item. The ItemList is instantiated at form creation. It persists for the life of the form. Each Item object is instantiated as needed. The form has a function called AddAcc. AddAcc is called via the on-change event of one of the form's controls.

What happens during this on-change event:

  1. AddAcc is called
  2. AddAcc create a new Item object
  3. AccAdd calls ItemList.AddItem and passes the Item by reference
  4. AddItem places Item object at the tail of the list

I’ve tested AddItem and it works well. My problem is that each time *AddAcc*is called it obtains the same memory location. I’ve tried different means of creating a new Item object. I’ve used New, GetMem (w/ FillChar), and instantiating a local variable of type Item. All calls to AddAcc results in the same memory location being obtained.

I’ve passed the Item object directly (by reference) to AddItem and alternatively passed a pointer to the Item object.

I thought that a reference (pointer) to an instance of the Item object within the linked list would ensure the Item's memory location would be maintained. It appears, however, that it is being collected once the AddAcc class is exited.

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;

Any help is greatly appreciated.

1
Please can we have some code. Once we see your code, we'll tell you what's wrong in it.David Heffernan
Please post the code of the code that calls AddAcc, the AddAcc method itself, the lines of code where you declare the ListItem object, and the lines of code where you initialize it. Basically, declarations, initialization, AddAcc + at least one of the places that call AddAcc (and all the code from the method that calls it, not just the line of code that calls it)Lasse V. Karlsen
I can guess that you are passing the address of a local variable containing a pointer.David Heffernan
@David Definitely sounds like it.Lasse V. Karlsen
Could you post the real code, this isn't even Pascal. Functions have return values. Could you include type definitions for Item and ptrItem.David Heffernan

1 Answers

1
votes

Here's how I'd write a linked list:

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;

When you need to deallocate your list you do this:

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

It is my belief that this is the canonical way of writing linked list type code in Pascal.

I've intentionally written this code for this simplest linked list imaginable. That allows you to focus on the allocation, use of pointers etc. You appear to already know how to maintain the references in your more complex list and so I believe you will have no trouble adapting this style of code to your needs.