Форум: "Основная";
Текущий архив: 2003.10.09;
Скачать: [xml.tar.bz2];
ВнизРекурсивная процедура не компилится D7... Найти похожие ветки
← →
KIR (2003-09-25 13:16) [0]... хотя в D6 все работало ОК. Точнее она (процедура) компилится, но при запуске прложение выдает ошибку
"List index out of bounds(0)"
.
Процедура рекурсивно загоняет данные из, я думаю, хорошо всем знакомой таблицыID PARENID NAME
в TreeView
← →
Anatoly Podgoretsky (2003-09-25 13:23) [1]Ошибка индекса массива, списка и т.д.
Программа написана неверно.
← →
KIR (2003-09-25 13:46) [2]Вот полный код (предполагаю, что омибка в методах Create и Free), но что странно на D6 все шло...
Код:
procedure TMainForm.BuildTree(Tree: TTreeView; Root: TExtendedNode; Tp: Integer);
var
ExtNode: TExtendedNode; //описание TExdendedNode см ниже.
DS: tpFIBDataSet;
S: String;
begin
If Root = nil then
S := "PARENTID is null"
else
S := "PARENTID = "+IntToStr(Root.ID);
DS := tpFIBDataSet.Create(nil);
DS.SQLs.SelectSQL.Add("SELECT");
DS.SQLs.SelectSQL.Add("*");
DS.SQLs.SelectSQL.Add("FROM");
DS.SQLs.SelectSQL.Add("GOODS");
DS.SQLs.SelectSQL.Add("WHERE");
DS.SQLs.SelectSQL.Add(S);
DS.SQLs.SelectSQL.Add("AND");
DS.SQLs.SelectSQL.Add("Del = 0");
DS.SQLs.SelectSQL.Add("ORDER BY");
DS.SQLs.SelectSQL.Add("ID");
DS.Transaction := DM1.DefaultTS;
DS.Open;
DS.First;
While not DS.Eof do
begin
ExtNode := Tree.Items.AddChild(Root,DS["Name"]) as TExtendedNode;
ExtNode.ID := DS["ID"];
ExtNode.ItemName := DS["Name"];
If DS["Last"] =1 then
ExtNode.Cost := DS["Cost"];
ExtNode.Kod := DS["Kod"];
ExtNode.IsBonus := DS["IsBonus"];
If DS["Last"] = 1 then
begin
ExtNode.Text := IntToStr(DS["Kod"])+" - "+FormatFloat("#,##0.",DS["Cost"])+" - "+ExtNode.Text+
" "+IntToStr(DS["KolVo"])+" "+IntToStr(DS["Bron"])+" "+IntToStr(DS["Kredit"]);
ExtNode.Last := True;
ExtNode.KolVo := DS["KolVo"];
ExtNode.Bron := DS["Bron"];
ExtNode.Kredit := DS["Kredit"];
end
else
begin
ExtNode.Last := False;
ExtNode.KolVo := -1;
ExtNode.Bron := -1;
ExtNode.KolVo := -1;
end;
DS.Free;
BuildTree(Tree,ExtNode,Tp);
DS.Next;
end;
DS.Free;
end;
описание TExtendedNode:
TExtendedNode = class(TTreeNode)
private
FID: Integer;
FKod: Variant;
FItemName: String;
FCost: Extended;
FKolVo: Integer;
FBron: Integer;
FKredit: Integer;
FLast: Boolean;
FIsBonus: Byte;
public
property ID: Integer read FID write FID;
property Kod: Variant read FKod write FKod;
property ItemName: String read FItemName write FItemName;
property Cost: Extended read FCost write FCost;
property KolVo: Integer read FKolVo write FKolVo;
property Bron: Integer read FBron write FBron;
property Kredit: Integer read FKredit write FKredit;
property Last: Boolean read FLast write FLast;
property IsBonus: Byte read FIsBonus write FIsBonus;
← →
Hooch (2003-09-25 13:56) [3]в Tools\Debugger options\Language exceptions поставь Stop on Delphi Exceptions и погляди где ошибка вываливается
← →
Palladin (2003-09-25 13:56) [4]DS.Free; что за фигня? как это понимать?
← →
Плохиш_ (2003-09-25 14:01) [5]>KIR © (25.09.03 13:46) [2]
DS.Free;
BuildTree(Tree,ExtNode,Tp);
DS.Next;
Вот это мне больше всего понравилось ;-)
← →
Palladin (2003-09-25 14:03) [6]я именно про это, странно что List index out of bounds...
хотя это наверно есть последствия "жизни после смерти"...
← →
KIR (2003-09-25 16:01) [7]Вообще убрал DS.Free - заработало... но, если я все правильно понимаю, при каждом последующем погружении в рекурсию создается очередной DS, так? И если их не убивать (DS.Free) они (DSы) так и будут висеть в памяти...
А насчет того, что предложил Плохиш_ - ничего не выйдет, потому что построится только одна ветка, а их много (очень)!
P.S. И еще раз: народ, на D6 все работало!?
← →
Плохиш_ (2003-09-25 16:13) [8]>KIR © (25.09.03 16:01) [7]
> А насчет того, что предложил Плохиш_
Интересно, что же предложил Плохиш_? Вообще-то был просто приведён кусок кода из KIR © (25.09.03 13:46) [2]
> Вообще убрал DS.Free - заработало...
Palladin, ты представляешь какой он DS.Free убрал? 8-O
← →
Palladin (2003-09-25 16:19) [9]неа... возможно оба...
> KIR © (25.09.03 16:01) [7]
Ты себе в уме представляешь исполнение этой процедуры?
← →
Verg (2003-09-25 16:24) [10]
> И если их не убивать (DS.Free) они (DSы) так и будут висеть
> в памяти...
Да пока цепь рекурсии продолжется они будут, и они ДОЛЖНЫ висеть.
В конце процедуры, т.е. пере выходом есть же ds.free, так что с этим все в порядке.
> P.S. И еще раз: народ, на D6 все работало!?
Случайно. Free освобождает память но ведь не "напрочь" же :))
Так или сяк устроен менеджер кучи у той или иной дельфы - от этого зависит какие будут чудеса твориться при обращении к освобожденной памяти и будут ли эти чудеса заметны "невооруженным глазом" вообще.
Так что, подумайте еще раз о том - что есть рекурсия и что есть динамические объекты в ее контексте.
P.S.
Я бы D7 спасибо сказал, что она хоть и криво, но дала понять где "дыра" в программе.
← →
KIR (2003-09-25 18:47) [11]Было, конечно, так: (2 Плохиш_: Сорри)
//DS.Free;
BuildTree(Tree,ExtNode,Tp);
DS.Next;
DS.Free;
Но все равно глючит, а если так:
//DS.Free;
BuildTree(Tree,ExtNode,Tp);
DS.Next;
//DS.Free;
Все ОК... не пойму, в чем проблема
← →
Verg (2003-09-25 18:54) [12]Давай ка педантично -
.....
> end;
>// DS.Free;
> BuildTree(Tree,ExtNode,Tp);
> DS.Next;
> end; // цикла while
> DS.Free;
> end; // процедуры
Так ?
← →
KIR (2003-09-25 19:00) [13]>Verg совершенно верно, только
DS.Free
заклментированны и там и там. Т.е. методDS.Free
не вызывается никогда и только тогда все работает...
← →
Плохиш_ (2003-09-25 19:05) [14]>KIR © (25.09.03 19:00) [13]
Так, ладно, будем спрашивать дальше.
На какой строчке происходит ошибка?
← →
KIR (2003-09-25 19:08) [15]>Плохиш_ (25.09.03 19:05) [14]
На вызове процедуры из самой себя
← →
Плохиш_ (2003-09-25 19:41) [16]>KIR
В какой версии говоришь это работало
ExtNode := Tree.Items.AddChild(Root,DS["Name"]) as TExtendedNode;
Ты представляешь, что ты здесь делаешь? 8-O
Ты используешь TTreeNode как TExtendedNode
Так бегом в хелп и читай всё, что относится к TTreeNodes, TTreeNode. Особенно надо обратить внимание на TTreeNode.Data
← →
Плохиш_ (2003-09-25 19:47) [17]так маленький пардон :-)
AddChild создаёт элемент TTreeNode, который не имеет дополнительных полей из TExtendedNode и соответственно не отводит под них память!
Тебе надо создать также нового потомка от TTreeView и переписать в нём AddChild.
← →
KIR (2003-09-25 20:00) [18]>Плохиш_ (25.09.03 19:47) [17]
>Тебе надо создать также нового потомка от TTreeView и переписать в нём AddChild.
А при чем тутDS.Free
?
Еще раз: если комментируюDS.Free
, все отлично работает, в том числе иAddChild
. Информация из дополнительных полей считывается, так что переписыватьAddChil
, по-моему, нет смысла
← →
Плохиш_ (2003-09-26 10:53) [19]>KIR © (25.09.03 20:00) [18]
> так что переписывать AddChil, по-моему, нет смысла
Хозяин, как говорится, барин :-|
Попробую ещё раз на пальцах: AddChild создал тебе компонент TTreeNode размером, скажем, 50 байт. Ты говоришь фигушки я буду использовать его как TExtendedNode который имеет размер 80 байт.
Как ты думаешь, что происходит, когда ты пишешь в последнии 30 байт? И так много, много раз.
Если ты интересуешься, то это в мире называется "Проблема переполнения буфера"
← →
KIR (2003-09-26 12:04) [20]>Плохиш_ (26.09.03 10:53) [19]
К вопросу об AddChild: если будет желание, загляни в эту ветку завтра или сегодня вечером. Я посмотрю дома поточнее - пример TExtendedNode я взял из Марко Кэнту, кстати, если эта книжка у тебя под рукой, можешь сам полюбопытствовать.
← →
Плохиш_ (2003-09-26 14:28) [21]>KIR © (26.09.03 12:04) [20]
Я не знаю, что ты делаешь в программе, но я думаю, что самый лёгкий и надёжный способ, это сделать TExtendedNode обычным классом и сохранять указатель на него в TTreeNode.Data.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.10.09;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.014 c