Implementing the destructor for this singly linked list class in Object Pascal, why is there always one memory block left unfreed at the end?
I have tried an iterative instead of recursive destructor but it gives the same result.
LinkedListMWI.pas
{$mode objfpc}{$H+}{$J-}
unit LinkedListMWI;
interface
uses SysUtils;
type
TNode = class
private
var
FData: Integer;
FNext: TNode;
public
constructor Create(Data: Integer);
destructor Destroy(); override;
end;
TLinkedList = class
private
var
FHead: TNode;
public
constructor Create(Items: Array of Integer);
destructor Destroy(); override;
end;
implementation
constructor TNode.Create(Data: Integer);
begin
inherited Create();
Self.FData := Data;
Self.FNext := Nil;
end;
destructor TNode.Destroy();
begin
FreeAndNil(Self.FNext);
inherited Destroy();
end;
constructor TLinkedList.Create(Items: Array of Integer);
var
Head, Last, ThisNode: TNode;
ThisItem: Integer;
begin
inherited Create();
Head := Nil;
for ThisItem in Items do
begin
ThisNode := TNode.Create(ThisItem);
if not Assigned(Head) then
begin
Head := ThisNode;
Last := Head;
end
else
begin
Last.FNext := ThisNode;
Last := ThisNode;
end;
end;
Self.FHead := Head;
end;
{ TODO Still one block unfreed }
destructor TLinkedList.Destroy();
begin
FreeAndNil(Self.FHead);
inherited Destroy;
end;
end.
MWI.lpr
{$mode objfpc}{$H+}{$J-}
program mwi;
uses SysUtils, LinkedListMWI;
var
Nums: Array of Integer = (1, 2, 3, 4, 5, 6, 7);
List: TLinkedList;
begin
List := TLinkedList.Create(Nums);
FreeAndNil(List);
end.
Compile with fpc -vwhine -glh MWI.lpr
Result:
15 memory blocks allocated : 1524/1536
14 memory blocks freed : 1496/1504
1 unfreed memory blocks : 28
True heap size : 360448
True free heap : 360192
Should be : 360224
Call trace for block $0000FFFF80105500 size 28
$0000000000400210 main, line 11 of MWI.lpr
$0000000000400168
The linked list code has no memory leak - the unfreed block is from somewhere else.
I don't know how FPC handles global dynamic array variables that are initialized - if I had to guess I would say it is that.
Try changing the code to this and check again:
var
List: TLinkedList;
begin
List := TLinkedList.Create([1, 2, 3, 4, 5, 6, 7]);
FreeAndNil(List);`
end.