Search code examples
pointersfreepascal

Using Dispose in FreePascal


Let’s say I have a linked list in FreePascal. The type would look something like this:

type
  PList = ^TList;
  TList = record
          x: integer;
          Next: PList;
          end;

var
  myList :PList;

So if I use dispose(myList) are then disposed all pointers in myList? Or just a first one pointing on the first element of myList?


Solution

  • No, disposing of myList (which should be of type PList by the way) will only dispose of the first item in the list. That's because the compiler knows nothing about how you're using the individual fields in the record.

    For example you may be using a skip list or doubly linked list, both of which would require two pointers within the record.

    The way to dispose of an entire list is as follows.

        var myList, listPtr, nextPtr : PList;
        :
        listPtr := myList;            (* start at start, obviously *)
        myList := nil;                (* mark list as empty        *)
        while listPtr <> nil do       (* continue until end        *)
        begin
            nextPtr := listPtr^.next; (* save pointer to next      *)
            dispose (listPtr);        (* kill current              *)
            listPtr := nextPtr;       (* move to next              *)
        end;
    

    The reason you need to save a pointer to the next record is because, once you dispose of the current one, you're not allowed to access its fields. So you have to save it before the dispose.

    This can be seen in the following complete program, which constructs a two element list, prints it, the disposes of the entire list.

    Program TestProg(output);
        type
            PList = ^TList;
            TList = record
                num : integer;
                next: PList;
            end;
    
        var
            myList  : PList;
            listPtr : PList;
            nextPtr : PList;
    begin
        (* Construct list 42 -> 99 -> 12 -| *)
    
        new (myList);
        new (myList^.next);
        new (myList^.next^.next);
        myList^.next^.next^.next := nil;
    
        myList^.num := 42;
        myList^.next^.num := 99;
        myList^.next^.next^.num := 12;
    
        (* Traverse list *)
    
        listPtr := myList;
        while listPtr <> nil do
        begin
            writeln (listptr^.num);
            listPtr := listPtr^.next;
        end;
    
        (* Clear list *)
    
        listPtr := myList;
        while listPtr <> nil do
        begin
            nextPtr := listPtr^.next;
            dispose (listPtr);
            listPtr := nextPtr;
        end;
        myList := nil;
    end.