Форум: "Основная";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];
ВнизОшибка при очистке дерева объектов! Найти похожие ветки
← →
WondeRu © (2005-06-06 18:36) [0]Здравствуйте, уважаемые!
Вот написал класс древовидной структуры. Дерево один раз заполняется с помощью AddChild, а затем анализируется GetChild.
Подскажите, почему при вызове Dispose возникает ошибка "Неверная работа с указателями"?unit uTree2;
interface
uses Classes;
type
TPNode = ^TNode;
TNode = record
Name: String[255];
Value: Integer;
Next: TPNode;
Childs: TPNode;
ChildCount: Integer;
end;
TTree = class
private
FTop: TPNode;
procedure FreeContent(ANode: TPNode);
public
constructor Create;
destructor Destroy; override;
function AddChild(AParent: TPNode): TPNode;
function GetChild(AParent: TPNode; Index: Integer): TPNode;
property Top: TPNode read FTop;
end;
implementation
{ TTree }
function TTree.AddChild(AParent: TPNode): TPNode;
begin
New(Result);
Result^.Name := "";
Result^.Value := 0;
Result^.Next := nil;
if AParent^.ChildCount = 0
then
AParent^.Childs := Result
else
GetChild(AParent, AParent^.ChildCount)^.Next := Result;
AParent^.ChildCount := AParent^.ChildCount + 1;
end;
constructor TTree.Create;
begin
New(FTop);
FTop^.Name := "Main";
FTop^.Value := 0;
FTop^.Next := nil;
end;
destructor TTree.Destroy;
begin
FreeContent(Top);
inherited;
end;
procedure TTree.FreeContent(ANode: TPNode);
var
i : Integer;
ATempNode: TPNode;
begin
for i := ANode^.ChildCount - 1 downto 0 do
begin
ATempNode := GetChild(ANode, i);
if ATempNode <> nil then
begin
FreeContent(ATempNode);
Dispose(ATempNode);
end;
end;
end;
function TTree.GetChild(AParent: TPNode; Index: Integer): TPNode;
var
i : Integer;
begin
Result := AParent^.Childs;
for i := 0 to Index - 2 do
if Result <> nil then
Result := Result^.Next;
end;
end.
← →
False_Delirium © (2005-06-06 23:34) [1]ЭТО работает ???
function TTree.AddChild(AParent: TPNode): TPNode;
begin
New(Result);
Result^.Name := "";
Result^.Value := 0;
Result^.Next := nil;
// где инициализируется ChildCount ?
if AParent^.ChildCount = 0
then
AParent^.Childs := Result
else
GetChild(AParent, AParent^.ChildCount)^.Next := Result;
AParent^.ChildCount := AParent^.ChildCount + 1; // какой здесь ChildCount ?
end;
До Dispose глаза не дошли ?
← →
ЮЮ © (2005-06-07 06:34) [2]В GetChild Index предполагается в интервале 1 ... ChildCount,
а цикл в FreeContent задается в интервале от ChildCount - 1 до 0
← →
novice_man © (2005-06-07 08:30) [3]В общем все уже сказано:
False_Delirium © (06.06.05 23:34) [1][Ответить]
> // где инициализируется ChildCount ?
При вызове NEW распределяется память под указатель и весь мусор, который находился в ячейках памяти, будет в полях Вашей записи. Так если Вы не инициализировали ChildCount то там может быть например положительное число. При получении последующего элемента Вы не проверяете наличие его, а просто ищете по for i := 0 to Index - 2 do ...
, где IndexANode^.ChildCount
, а там может быть что угодно и соответственно AV.
Таким образом нет соответствия между реальными указателями и счетчиками их.
Может лучше проверять не nil ли Childs у родителя и если указатель существует тогда выполнять Dispose&
← →
WondeRu © (2005-06-07 13:50) [4]учитывая замечания, переделываю:
function TTree.AddChild(AParent: TPNode): TPNode;
begin
New(Result);
Result^.Name := "";
Result^.Value := 0;
Result^.Next := nil;
Result^.Childs := nil;
Result^.ChildCount := 0;
if AParent^.ChildCount = 0
then
AParent^.Childs := Result
else
GetChild(AParent, AParent^.ChildCount)^.Next := Result;
AParent^.ChildCount := AParent^.ChildCount + 1;
end;
constructor TTree.Create;
begin
New(FTop);
FTop^.Name := "Main";
FTop^.Value := 0;
FTop^.Next := nil;
FTop^.Childs := nil;
FTop^.ChildCount := 0;
end;
destructor TTree.Destroy;
begin
FreeContent(Top);
inherited;
end;
procedure TTree.FreeContent(ANode: TPNode);
var
i : Integer;
ATempNode: TPNode;
begin
for i := ANode^.ChildCount - 1 downto 0 do
begin
ATempNode := GetChild(ANode, i);
if ATempNode <> nil then
begin
FreeContent(ATempNode);
Dispose(ATempNode);
end;
end;
end;
function TTree.GetChild(AParent: TPNode; Index: Integer): TPNode;
var
i : Integer;
begin
Result := AParent^.Childs;
for i := 1 to Index do
if Result <> nil then
Result := Result^.Next;
end;
end.
← →
Digitman © (2005-06-07 13:57) [5]
> WondeRu © (06.06.05 18:36)
это что, учебная задача ?
если не учебная, то к чему этот новый велосипед, если есть готовый TCustomTreeView ?
← →
WondeRu © (2005-06-07 15:10) [6]Digitman © (07.06.05 13:57) [5]
если не учебная, то к чему этот новый велосипед, если есть готовый TCustomTreeView
не учебная...
TCustomTreeView - визуальный компонент... да и прибавит моей dll-ке еще 200 кило... смысла нет его пользовать...
← →
Digitman © (2005-06-07 15:18) [7]
> WondeRu © (07.06.05 15:10) [6]
можно же поступить проще - взять за основу готовый класс TCustomTreeView и повыкидывать из него все визуальные дела, коль они не нужны
← →
WondeRu © (2005-06-07 15:25) [8]Digitman © (07.06.05 15:18) [7]
а смысл, если данное дерево используется лишь два раза, когда заполняется и когда удаляется? :) Велосипед есть, но... глянул я на TCustomTreeView, больно уж много чего он тянет за собой: TWinControl, TList, TTreeNode... а ампутацией заниматься не охота: овчинка выделки не стоит
← →
Digitman © (2005-06-07 15:30) [9]
> ампутацией заниматься не охота
а геморрой себе наживать со связными списками и с рекордом вместо класса слаще получается ?)
← →
WondeRu © (2005-06-07 15:37) [10]Digitman © (07.06.05 15:30) [9]
и с рекордом вместо класса слаще получается ?)
не слаще... но списки самопальные помучать никогда не мешает для самообразования :)
Да и такая структура будет экономичнее память расходовать при 100000 узлах дерева
← →
Digitman © (2005-06-07 15:40) [11]
> Да и такая структура будет экономичнее память расходовать
> при 100000 узлах дерева
не факт.
тут недавно в "Общие" обсасывалась проблема, где автор жаловался на грабли вида Out of memory .. найди эту ветку, почитай, вникни, где-что-как-почему экономится или наоборот
← →
WondeRu © (2005-06-07 15:46) [12]Digitman © (07.06.05 15:40) [11]
угу.. пасиб!
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.06.29;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.048 c