Já jsem dlouze přemýšlel v čem dělám chybu. Furt jsem myslel na to nil (element pole, jak se tam dostal). Pak mi to najednou došlo. Že to přižazování se tam děje ve dvou úrovních. První úroveň je nastavení délky pole pointerů... Tím se tam dostane to nil. A druhá úroveň je pak to, že ten pointer musí někam směřovat, tedy tomu objektu přidělím paměť... Takže jsem z toho konečně moudřejší.
Navíc jsem řešil jak si pohlídat dealokování všech těch elementů, abych to nedělal rekurzivně. Tak jsem vymyslel toto
destructor TTrackerRegex.Destroy();
var i: integer;
begin
{ Despose all objects from the last one
to the first one }
for i := info.AllSecPointers_currentIndex downto 0 do
Dispose(AllSecPointers[i]);
inherited;
end;
info.AllSecPointers_currentIndex se nastaví vždycky když allokuju paměť pro vnořenou sekci, čili nastavuju ukazatel pro element pole pointerů. A každý ukazatel si zazálohuju do pole, kde všechno sbírám. Toto pole je jednorozměrné, takže se vše dá snadno dealokovat.
Procedura pro alokování paměti vnořených objektů:
procedure TTrackerRegex.incSection(newLevel: boolean; pSec: pTRegex_sec = nil);
begin
if (pSec = nil ) then
begin
Sections := New(pTRegex_sec);
// Backup pointer
AllSecPointers[0] := Pointer(Sections);
info.AllSecPointers_currentIndex := 1;
// The root section parent is self
Sections.parent := Sections;
Sections.len := 0;
Sections.hasSections := false;
Sections.hasUnits := false;
exit;
end;
if (not newLevel) then
begin // EXPAND SECTION
setlength(psec.secs, psec.len+1);
psec.secs[psec.len] := New(PTRegex_sec);
// Backup pointer
AllSecPointers[info.AllSecPointers_currentIndex] := Pointer(Sections);
Inc(info.AllSecPointers_currentIndex);
if (info.AllSecPointers_currentIndex>length(AllSecPointers)) then
setLength(AllSecPointers,length(AllSecPointers)+10);
psec.secs[psec.len].parent := psec.secs[psec.len];
Inc(psec.len);
end
else
begin // CREATE NEW LEVEL INTO CURRENT SECTION
pSec.hasSections := true;
setlength(psec.secs, psec.len+1);
psec.secs[psec.len] := New(PTRegex_sec);
// Backup pointer
AllSecPointers[info.AllSecPointers_currentIndex] := Pointer(psec.secs[psec.len]);
Inc(info.AllSecPointers_currentIndex);
if (info.AllSecPointers_currentIndex>length(AllSecPointers)) then
setLength(AllSecPointers,length(AllSecPointers)+10);
psec.secs[psec.len].parent := psec;
Inc(psec.len);
end;
end;
Zítra bych tam mohl přidat try block. Já to normálně nepoužívám, ale tu by to nejspíš chtělo.
Dotaz:
Když to ladím stylem, že dám zarážku, alokuju paměť, zastavím na zarážce a pak restartuju debugger, tak dojde k "memory leak"? Protože debugger mi opakovaně padá.