Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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 ..., где Index ANode^.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.039 c
14-1117442964
leonidus
2005-05-30 12:49
2005.06.29
Как из lsd словарей Lingvo получить словари в текстовом виде?


14-1117951008
Гарри Поттер
2005-06-05 09:56
2005.06.29
Костя проиграл бой.


3-1116781037
M_Tania
2005-05-22 20:57
2005.06.29
Из FoxPro в SQL


14-1117181522
TUser
2005-05-27 12:12
2005.06.29
Уплотнение элементов в памяти


1-1118070261
Crazy_Diman
2005-06-06 19:04
2005.06.29
проблема Listbox





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский