Форум: "Начинающим";
Текущий архив: 2009.12.20;
Скачать: [xml.tar.bz2];
ВнизОшибка в коде, который раньше работал. Найти похожие ветки
← →
kyn66 © (2009-11-03 13:14) [0]Уважаемые мастера. Помогите найти ошибку в коде, взятом из рабочей программы:
1) Наполняем st данными
procedure FormSt;
Var
st : TStringList;
Bitmap1 : TBitmap;
begin
st := TStringList.Create;
Bitmap1 := TBitmap.Create;
ListBox1.Clear;
for i := 1 to KolLotery do
begin
DM1.ImageList1.GetBitmap(32, Bitmap1);
st.AddObject("первая запись", Bitmap1);
st.AddObject("вторая запись", Bitmap1);
st.AddObject("третья запись", Bitmap1);
end;
ListBox1.Items.AddStrings(st);
st.Free;
Bitmap1.Free;
end;
2) Отрисовываем ListBox с пиктограммами
procedure TMainFrm.ListBox1DrawItem(Control: TWinControl; Index: Integer;
Rect: TRect; State: TOwnerDrawState);
Var
Offset : Integer;
Bitmap : TBitmap;
begin
Offset := 0;
with TCustomListBox(Control).Canvas do
begin
FillRect(Rect);
Bitmap := TBitmap(ListBox1.Items.Objects[Index]);
if Bitmap <> nil then
begin
Bitmap.Transparent :=True;
BrushCopy(Bounds(Rect.Left + 2, Rect.Top + 2, Bitmap.Width, Bitmap.Height),
Bitmap, Bounds(0, 0, Bitmap.Width, Bitmap.Height), clWhite);
Offset := Bitmap.Width + 8;
end;
TextOut(Rect.Left + Offset, Rect.Top, Listbox1.Items[Index]);
end;{With}
end;
Ошибка вылетает на "жирной" строке
← →
Демо © (2009-11-03 13:22) [1]
> Ошибка вылетает на "жирной" строке
Что за ошибка? И что поменялось в окружении?
← →
Сергей М. © (2009-11-03 13:23) [2]
> который раньше работал
Он и раньше не мог работать.
Ты ж Bitmap1 собственноручно убиваешь
см.Bitmap1.Free
а потом обращаешься к трупу за свойством Transparent
)
← →
kyn66 © (2009-11-03 13:26) [3]Ошибка стандартнонепонятнаяоткудавзятая Access Violation.
> Ты ж Bitmap1 собственноручно убиваешь
Так я же его убиваю Bitmap1, который используется в первой процедуре и нужен только для наполнения st данными. А ошибка вылетает во второй процедуре и используется там Binmap, без цифирей.
← →
kyn66 © (2009-11-03 13:29) [4]
> Демо © (03.11.09 13:22) [1]
> > Ошибка вылетает на "жирной" строкеЧто за ошибка? И что
> поменялось в окружении?
Да собственно особо ничего. Раньше этот код работал в отдельной форме и объявлял я Bitmap в Interface формы, а убивал по Distroy формы. Вот и вся разница.
← →
Сергей М. © (2009-11-03 13:29) [5]
> используется там Binmap, без цифирей.
И что ?
Цифирь эта - всего лишь цифирь в идентификаторе лок.переменной.
Которая в строчкеBitmap := TBitmap(ListBox1.Items.Objects[Index]);
получает значение, равное копии указателя на объект, который ты собственноручно убил в 1-й процедуре.
← →
Игорь Шевченко © (2009-11-03 13:30) [6]
> if Bitmap <> nil then
if Bitmap is TBitmap
← →
Anatoly Podgoretsky © (2009-11-03 13:30) [7]> kyn66 (03.11.2009 13:14:00) [0]
Так и пишет "вылетаю на "жирной" строке"
← →
Dennis I. Komarov © (2009-11-03 13:30) [8]
> Ошибка стандартнонепонятнаяоткудавзятая Access Violation.
очень даже всегда понятная: Был "Вася" и нет его...
← →
Игорь Шевченко © (2009-11-03 13:30) [9]Упс. Ты вообще соображаешь, что пишешь ? Марш за книжки
← →
Сергей М. © (2009-11-03 13:31) [10]
> убивал по Distroy формы. Вот и вся разница
Т.е. убивал объект ты заведомо позже самого последнего обращения к нему.
А теперь ты сначала убил, а потом измываешься над трупом.
Вот и вся разница)
← →
kyn66 © (2009-11-03 13:31) [11]
> а потом обращаешься к трупу за свойством Transparent
И тем более ошибка в блоке после проверки Bitmap на nil
← →
Сергей М. © (2009-11-03 13:32) [12]
> в коде, который раньше работал
Раньше был другой код.
Потому и работал.
← →
Dennis I. Komarov © (2009-11-03 13:32) [13]
> И тем более ошибка в блоке после проверки Bitmap на nil
А с чего ты взял, что там nil?
← →
Сергей М. © (2009-11-03 13:34) [14]
> ошибка в блоке после проверки Bitmap на nil
А почему бы ей не быть не-nil ?
Ты же записал не-nil, вот она и прошла проверку.
А объект ты убил.
А ссылка на него осталась.
← →
kyn66 © (2009-11-03 13:34) [15]
> получает значение, равное копии указателя на объект, который
> ты собственноручно убил в 1-й процедуре.
Bitmap локально объявлен во второй процедуре и с успехом инициализируется там же
Bitmap := TBitmap(ListBox1.Items.Objects[Index]);
Терзают смутные сомнения по поводу корректной отработки st.AddObject("вторая запись", Bitmap1)...
← →
Сергей М. © (2009-11-03 13:35) [16]
> и с успехом инициализируется там же
>
мусором !
Объекта-то нет, ты уничтожил его до этого !
← →
Сергей М. © (2009-11-03 13:36) [17]
> смутные сомнения по поводу корректной отработки st.AddObject("вторая
> запись", Bitmap1)
Не терзайся, он работает абсолютно корректно - копирует строки и ассоциированные с ними ссылки.
← →
clickmaker © (2009-11-03 13:36) [18]> Bitmap локально объявлен во второй процедуре и с успехом
> инициализируется там же
>
> Bitmap := TBitmap(ListBox1.Items.Objects[Index]);
это не инициализация. Это присваивание значения указателя, который указывает уже на труп
← →
kyn66 © (2009-11-03 13:39) [19]
> Сергей М. © (03.11.09 13:34) [14]
Я дико извеняюсь, но закомментировал "убийство" Bitmap1 и все пошло нормально. Я подумал что он уже не нужен, поскольку Listbox1 уже наполнен данными... ListBox1.Items.AddStrings(st);
← →
Сергей М. © (2009-11-03 13:41) [20]
> акомментировал "убийство" Bitmap1 и все пошло нормально
Теперь тебя ждут другие грабли - утечка памяти
← →
Dennis I. Komarov © (2009-11-03 13:43) [21]
> Сергей М. © (03.11.09 13:41) [20]
Фигня то какая... Разве ее мало? Разве нас это заставит буквари читать?
← →
kyn66 © (2009-11-03 13:44) [22]Просто procedure FormSt; может повторяться несколько раз, поэтому и решил что нужно удалять ненужные объекты, так как в этой процедуре Bitmap1 создается заново
Bitmap1 := TBitmap.Create;
← →
kyn66 © (2009-11-03 13:45) [23]
> Сергей М. © (03.11.09 13:41) [20]
> Теперь тебя ждут другие грабли - утечка памяти
:) Сообщение появилось пока я про это и пмсал [22].
← →
clickmaker © (2009-11-03 13:47) [24]> Я подумал что он уже не нужен, поскольку Listbox1 уже наполнен
> данными
AddObject не копирует объект.
и почему бы не вызвать DM1.ImageList1.GetBitmap(32, Bitmap1); один раз?
а при закрытии программы убить глобальный объект Bitmap1
← →
kyn66 © (2009-11-03 13:48) [25]2Сергей М.
Как посоветует мастер поступить в такой ситуации? Чтобы и волки были сыты......
← →
kyn66 © (2009-11-03 13:51) [26]
> и почему бы не вызвать DM1.ImageList1.GetBitmap(32, Bitmap1);
> один раз?а при закрытии программы убить глобальный объект
> Bitmap1
Согласен, так можно и сделать. У Bitmap1 небольшая смысловая нагрузка, в плане просто картинку передать и все. Можно его отдельно создать и главное потом не забыть его удалить по завершении.
← →
Сергей М. © (2009-11-03 13:51) [27]Вернись к варианту, котоый был раньше ("работал").
И вынеси GetBitmap из тела цикла.
← →
Сергей М. © (2009-11-03 13:53) [28]
> главное потом не забыть его удалить по завершении
Можешь даже и не удалять - система не обеднеет, это для нее не потеря.
← →
Демо © (2009-11-03 14:06) [29]
> Сергей М. © (03.11.09 13:53) [28]
>
> > главное потом не забыть его удалить по завершении
>
>
> Можешь даже и не удалять - система не обеднеет, это для
> нее не потеря.
>
>
Ж-))
← →
kyn66 © (2009-11-03 14:45) [30]
> Сергей М. © (03.11.09 13:51) [27]
> Вернись к варианту, котоый был раньше ("работал").И вынеси
> GetBitmap из тела цикла.
Все понял! Спасибо!
Тема закрыта.
← →
kyn66 © (2009-11-03 15:59) [31]2Сергей М. ©
Я извеняюсь, не вовремя объявил о закрытии темы. Хотел задать еще один вопрос , а чем от Bitmap1 отличается st. При уничтожении Bitmap1 возникает ошибка(правильная), а при уничтожении st ошибки нет? Чем они отличаются?
...
st.AddObject("третья запись", Bitmap1);
end;
ListBox1.Items.AddStrings(st);
st.Free;
Bitmap1.Free;
end;
[0]
Спецом решил уничтожить st и все работает...
← →
clickmaker © (2009-11-03 16:16) [32]> чем от Bitmap1 отличается st
тем, что AddObject НЕ копирует объект, а AddStrings - копирует строки в листбокс
← →
Германн © (2009-11-03 16:19) [33]
> Я извеняюсь, не вовремя объявил о закрытии темы. Хотел задать
> еще один вопрос , а чем от Bitmap1 отличается st. При уничтожении
> Bitmap1 возникает ошибка(правильная), а при уничтожении
> st ошибки нет? Чем они отличаются?
>
Они ничем не отличаются друг от друга. Обе - локальные переменные процедуры FormSt.
А отличие указано в
> clickmaker © (03.11.09 13:47) [24]
>
> > Я подумал что он уже не нужен, поскольку Listbox1 уже
> наполнен
> > данными
>
> AddObject не копирует объект.
← →
kyn66 © (2009-11-03 16:20) [34]
> а AddStrings - копирует строки в листбокс
Но в данном случае копируются строки, содержащие указатель на объект, который нельзя уничтожать (Bitmap1). Как это увязывается вместе?
← →
clickmaker © (2009-11-03 16:40) [35]> Как это увязывается вместе?
так, что строки - управляемый объект. Для них VCL выделяет память и следит за ссылками. А про абстрактный объект метод ничего не знает. Там может быть и record и просто число типа int
← →
Германн © (2009-11-03 17:43) [36]
> Но в данном случае копируются строки, содержащие указатель
> на объект, который нельзя уничтожать (Bitmap1). Как это
> увязывается вместе?
Если подумать, то этот вопрос сам в себе содержит и точный ответ и ошибку в понимании основ. :)
← →
kyn66 © (2009-11-03 17:50) [37]
> clickmaker © (03.11.09 16:40) [35]
Спасибо.
← →
kyn66 © (2009-11-05 10:50) [38]Уважаемые мастера! Прошу разъяснить еще раз, ну не могу понять связи.... См.[0]. Какая связь между двумя переменными Bitmap1(объявлена в первом блоке кода) и Bitmap(объявлена во втором блоке). Все сделал как говорили, все работает, но хочу глубже разобраться. В сети нашел почти аналогичный пример http://demi-s.narod.ru/components/034.html Тм тоже ListBox получает картинки из объекта. Так вот, в блоке примераListBox1DrawItem тоже объявлена как и у меня переменная Bitmap и после отрисовки она уничтожается. В своей программе я объявил Bitmap1 : TBitmap глобально и уничтожаю ее после деактивации основной формы. Но стоит мне в своем втором блоке уничтожить переменную Bitmap после отрисовки ListBox, при закрытии программы вылетает ошибка Access violation по отношению к глобальнообъявленной переменной Bitmap1
procedure TMainFrm.FormDestroy(Sender: TObject);
begin
Bitmap1.Free;
end;
Разъясните спокойно, без эмоций, какая между ними связь? И почему при уничтожении локально объявленной Bitmap теряется связь с глобально объявленной Bitmap1. Спасибо.
← →
Сергей М. © (2009-11-05 10:54) [39]
> Какая связь между двумя переменными Bitmap1(объявлена в
> первом блоке кода) и Bitmap(объявлена во втором блоке)
Обе переменные содержат значение, являющее собой указатель на один и тот же объект.
← →
RWolf © (2009-11-05 10:58) [40]в Дельфи Bitmap:TBitmap — на самом деле указатель на объект.
Строкой DM1.ImageList1.GetBitmap(32, Bitmap1); ты присваиваешь ему адрес реально существующего объекта, который хранится в ImageList1. Кроме того, этим же объектом пользуется процедура ListBox1DrawItem. Кода ты выполняешь Bitmap.Free, объект уничтожается, и при обращеннии по его адресу из другого места программы имеем глюк.
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2009.12.20;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.008 c