При реализации деструктора для этого класса односвязного списка в Object Pascal, почему в конце всегда остается один незанятый блок памяти?
Я пробовал использовать итеративный деструктор вместо рекурсивного, но он дает тот же результат.
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.
Скомпилируйте с помощью fpc -vwhine -glh MWI.lpr
Результат:
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
В коде связанного списка нет утечки памяти — несвободный блок взят откуда-то еще.
Я не знаю, как FPC обрабатывает инициализированные глобальные переменные динамического массива - если бы мне пришлось догадываться, я бы сказал, что это так.
Попробуйте изменить код на этот и проверьте еще раз:
var
List: TLinkedList;
begin
List := TLinkedList.Create([1, 2, 3, 4, 5, 6, 7]);
FreeAndNil(List);`
end.