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
?
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.