![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Dispose
TUser © (2004-08-14 10:36:00)Пол-ночи просидел, никак не могу понять, где ошибка в таком коде
pcat:=FCatalog;
while pcat <> nil do begin
pcat1:=pcat^.Next;
pcl:=pcat^.First;
while pcl <> nil do begin
pcl1:=pcl^.Next;
pch:=pcl^.First;
while pch <> nil do begin
pch1:=pch^.Next;
try
if pch^.AutoFree then // begin
// if assigned(pch^.Control) then
FreeAndNil(pch^.Control)
{end} else pch^.Control:=nil;
except
// if Control is alreadey destroyed by user
end;
Dispose(pch);
pch:=pch1;
end;
if assigned(pcl^.Font) then
FreeAndNil(pcl^.Font);
Dispose(pcl);
pcl:=pcl1;
end;
Dispose(pcat);
pcat:=pcat1;
end;
if assigned(FList) then
FList.Free;
Поясню. Есть дерево из нескольких уровней, корень его - FCatalog. Я совершаю его обход и освобождаю занятую память. Там, где есть ссылки на объекты - их я дестрою. То, что память выделена, все ссылки присвоены правильно, если нет ничего - то nil, и дерево построено правильно и т.д. - это я говорю совершенно точно и уверен на 100%. С этим деревом программа работает и до тех пор, пока не начнет выполняться этот код все работает нормально. Короче говоря, нет у меня подозрений на какую-то тривиальную ошибку.
А этот код выполняется нестабильно. Иногда выполняется, иногда при возникает AV. Причем даже так - подряд какое-то количество раз все выполняется нормально, а потом вдруг начинается глюк. Много раз подряд глючит, потом опять все нормально.
Отладчик говорит, что ошибки возникают на Dispose'ах. При этом Ctrl+F7 показывает, что соотвествующий указатель куда-то указывает и там действительно лежит некоторое (причем правильное) значение. Т.е. вроде бы попытка высвободить эту память не должна привождить к ошибкам.
В чем тут может быть дело.
TUser (2004-08-14 12:42:00) [21]Мешает то, что на разных уровнях дерева узлы разные. Например на уровне pcl расположены PCell = ^TCell, а одним из элементов этого TCell является TFont, которого нет на других уровнях. А на самом нижнем уровне есть TControl, которого на более высоких уровнях нет. Ну и т.д.
А обход дерева таким способом - это вполне нормальное дело, тут проблема не в алгоритме обхода, а с дестроем объектов и работе с памятью. Только вот я никак не могу найти этот баг.
Sergey Kaminski (2004-08-14 12:22:00) [22]Например, что мещает сделать вот таким образом (пример, разумеется, схематический):
procedure DeleteRecursively (ASubNode: TMyNode);
var
I: Integer;
begin
for I := 0 to ASubNode.Count-1 do
begin
DeleteRecursively (ASubNode[I]);
end;
ASubNode := nil;
end;
begin
DeleteRecursively (FCatalog); // это все :)
end.
going down recursively.... (c)
:-)
Sergey Kaminski (2004-08-14 12:12:00) [23]ИМХО, пытаясь анализировать _такой_ код, можно потратить пол-ГОДА.
Кажется, имеет смысл сделать обход дерева не столь причудливым образом, а просто, именно - используя рекурсивный алгоритм.
А то ведь можна рехнуться в этих pcat,pcat1,pch,pch1,pcl...я серъёзно :( они ведь еще внутриwhileнеоднократно замословатейшим образом изменяются, тут не уследишь...
Удачи.