Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.11.21;
Скачать: CL | DM;

Вниз

Глюки Делфи 6   Найти похожие ветки 

 
DelphiN! ©   (2004-10-30 14:01) [0]

Сегодня обнаружил глюк компилятора Делфи 6:

procedure Button1Click(Sender: TObject);
var
 strl: TStringList;
 i: Integer;
 Item: TListItem;
 Ico:TIcon;
 A: array [0..78] of Char;
 dd:integer;
begin

 if DirectoryDialog1.Execute then
 begin
   //Допустим Edit1.text теперь = C:\1
   Edit1.Text := SelectDirectoryDialog1.Directory;
   strl := TStringList.Create;
   //В strl теперь список файлов каталога C:\1
   strl := Main.FindUnderFiles(Edit1.Text,"*.exe");
   //Очищаю ImageList
   Icons.Clear;
   //В dd теперь кол-во элементов strl-а, допустим 37-1=36
   dd:=(strl.Count-1);
   for i := 0 to dd do //Цикл от 0-я до 36-ти
   begin
     //Добавляю в ListView строку
     Item := ListView1.Items.Add;
     //Заполняю созданую в ListView строку
     //Ошибка вылетает тут: ListIndex out of Bounds(37)
     //при !!!37-ом(должно быть только 36)!!! обороте цикла
     Item.Caption := strl.Strings[i];
     //Копирую строку в А
     StrPCopy(A, strl.Strings[i]);
     //Добавляю в Image1.Picture.Icon иконку файла
     //Путь к которому содержиться в A
     Image1.Picture.Icon.Handle := ExtractIcon(HInstance, A, 0);
     //Добавляю иконку из Image1 в ImageList
     Icons.AddIcon(Image1.Picture.Icon);
     //Присваиваю полю ListView-a номер иконки
     Item.ImageIndex := i;
     //без этой сроки Создается исключение:
     //List index out of Bounds (37)
     IF I=DD THEN BREAK;  
   end
 end
end;

Чем может быть вызвано данное исключение? Код на мой взгляд абсолютно правильный, и до 37-го элемента цикл дойти никак не может, но тем немение это происходит, почему? Это глюк Делфи, или я уже совсем переработал?


 
Palladin ©   (2004-10-31 04:07) [1]

Это твой глюк естественно...
объясни...
на кой черт тебе нужно было писать
StrPCopy(A, strl.Strings[i]);
когда можно написать
a:=copy(strl[i],1,79)
?

если не видишь разницы между array [0..78] of char (кстати на кой черт этот массив нужен?) и PChar то не стоит пользоватся функциями работаюзщими со строками и принимающими PChar...


 
DiamondShark ©   (2004-10-31 11:13) [2]


>      StrPCopy(A, strl.Strings[i]);

А если строка длиннее 78 символов?


 
Юрий Зотов ©   (2004-10-31 11:20) [3]

> ... обнаружил глюк компилятора

Если водитель врезался в столб, то виноват столб?


 
DiamondShark ©   (2004-10-31 11:22) [4]


> Если водитель врезался в столб, то виноват столб?

Нет. Автомобиль.


 
Anatoly Podgoretsky ©   (2004-10-31 12:01) [5]

Кто угодно, только не водитель.
В процедуре надо не ошибки убирать, а всю процедуру с нуля переписать.


 
Cobalt ©   (2004-10-31 12:36) [6]

Попробуй использовать отладку - и посмотреть, какие переменные имеют какие значения - там и увидишь, что к чему.


 
VID ©   (2004-10-31 12:57) [7]

Приведённый тобою код, каким кривым  он бы не являлся, никак не должен давать 37-ой итерации в цикле... что что-то темнишь...


 
VID ©   (2004-10-31 12:59) [8]

т.е. 38 итерации


 
VID ©   (2004-10-31 13:06) [9]

и ещё, как бы там ни было, но заранее (пока ты ещё возможно не стал "великим мегапрограммером") хочу обратить твоё внимание на то, что объекты типа TStringList после создания и использования надо и уничтожать. Если ты думаешь что lst:TStringList, объявлен в теле процедуры и будет уничтожен автоматически при выходе из процедуры - ты ошибаешься. У тебя будет утечка памяти. Удалять такие объекты лучше всего так

Lst := TStringList.Create;
try
 // здесь выполняем весь код, которому требуется этот lst
finally
 Lst.free;
end;


Также обрати внимание на то что к элементам списка TStringList можно обращаться не только через метод Strings (lst.strings[i]) но и напрямую - lst[i].

Переменная dd (dd:=(strl.Count-1)) вообще не нужна. Правильней будет такая запись:
For I:=0 to strl.count-1 do....

И ещё... Ближайшие четыре-пять лет не говори, что нашёл у комплятора дельфи глюк ;) Рано тебе ещё :)


 
Palladin ©   (2004-11-01 06:01) [10]


> [7] VID ©   (31.10.04 12:57)

ошибаешься


 
DelphiN! ©   (2004-11-01 07:20) [11]

>Palladin ©   (31.10.04 04:07) [1]
Ну а почему появляется лишняя интерация я так и не понял,
и какая разница между
StrPCopy(A, strl.Strings[i]);
       и
a:=copy(strl[i],1,79)

Когда прогоняю под отладчиком, он сразу пишет что strl.count-1 = strl.count, тоесть -1 он не учитывает ...


 
KSergey ©   (2004-11-01 09:41) [12]

> [11] DelphiN! ©   (01.11.04 07:20)
> StrPCopy(A, strl.Strings[i]);
>        и
> a:=copy(strl[i],1,79)

В первом случае копируется до первого встретившегося в памяти символа с кодом 0, во втором - ровно 79 байт, не больше и не меньше.

> Когда прогоняю под отладчиком, он сразу пишет что
> strl.count-1 = strl.count

Чего??? Это как так???


 
DelphiN! ©   (2004-11-02 07:50) [13]

Вобщем так:

присваиваю переменной dd значение strl.count-1(dd := strl.count-1), теперь если strl.count = 37, то dd = 36(все правильно).

Далее делаем цикл (for i := 0 to dd do ... ) Цикл будет выполнять и 37-ю итерацию, хотя dd = 36! Данный глюк возникает только в вышеприведенном мной коде. Если заменить строку for i := 0 to dd do на for i := 0 to strl.count-1 do ничего не изменится.

Как только программа входит в цикл содержимое dd под отладчиком не показывается(подсказка не появляется), но на 36-й итерации условие "IF I=DD THEN BREAK;" выполняется, из этого следует что dd = 36, однако если убрать строчку IF I=DD THEN BREAK;, то цикл выполняет 37-ю итерацию, при том что dd=36!!! Почему??


 
sniknik ©   (2004-11-02 08:35) [14]

может не понимаю чего, но
for i := 0 to 36 do ...
ровно 37 итеаций, и это правильно!
для 36-и (если вдруг это надо) будет
for i := 1 to 36 do ...

непонимаю где ошибка, в чем?


 
DelphiN! ©   (2004-11-02 10:34) [15]

sniknik ©   (02.11.04 08:35) [14]

Я считаю с 0-я. Появляется лишняя итерация. Если сделать примерно такую структуру то все будет работать:

for i := 0 to 36 do

//В нормальном цикле BREAK никогда не выполнится, но в
//приведенном мной выше коде выполняется
if i = 37 then BREAK;


 
sniknik ©   (2004-11-02 11:23) [16]

ключевое слово в нормальном. ;о)))

у тебя вот это обьявление
...
A: array [0..78] of Char;
dd:integer;
...
росполагает переменную dd сразу после масива A
а
StrPCopy(A, strl.Strings[i]);
ExtractIcon(HInstance, A, 0);
работают с масивом как областью память (без учета переполнения) и вероятно просто перетирают значение dd который лежит прамо за массивом.

сделай массив побольше (проверь), намного больше например A: array [0..1078] of Char;
и/или перенеси обьявление dd перед массивом.
ситуация должна измениться.
(это просто для понимания ситуации, а лучше прислушатся к советам даваемым ранее)


 
Palladin ©   (2004-11-02 17:56) [17]

не вероятно перетирают, а точно перетирают...


> [15] DelphiN! ©   (02.11.04 10:34)

обратил бы внимание на указание что PChar это совсем не array [0..78] of char давно бы уже во всем разобрался... но нет... не слушаешь что тебе говорят...


 
DelphiN! ©   (2004-11-03 06:25) [18]

Ясно, всем большое спасибо!



Страницы: 1 вся ветка

Текущий архив: 2004.11.21;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.045 c
1-1099646621
Ш-К
2004-11-05 12:23
2004.11.21
Поиск элемента множества по его естественному порядку.


14-1099658239
}|{yk
2004-11-05 15:37
2004.11.21
Суперзагадка дня


14-1099881443
Думкин
2004-11-08 05:37
2004.11.21
С днем рождения! 8 ноября


1-1100152104
Sidek
2004-11-11 08:48
2004.11.21
Навигация в ClientDataSet-е


3-1098653257
Alek_1
2004-10-25 01:27
2004.11.21
Ошибка в представлении