![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Строку в объект [D7, XP]
kyn66 © (2009-11-12 16:11:00)Подскажите, каким способом можно строку вставить в объект , ну например ComboBox ? Нужно к примеру просканировать текущий каталог диска, найденные файлы записать в Combobox, а полный путь к файлу сохранить в объекте. Помню со строками есть проблемы при сохранении в объект. Есть вот такой вариант
....
var
PS: PString;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
new(PS);
PS^ := 'Hello world 1';
ComboBox1.Items.AddObject('Item1', TObject(PS));
PS^ := 'Hello world 2';
ComboBox1.Items.AddObject('Item2', TObject(PS));
PS^ := 'Hello world 3';
ComboBox1.Items.AddObject('Item3', TObject(PS));
...
procedure TForm1.FormDestroy(Sender: TObject);
begin
Dispose(PS);
end;
При доступе к объекту
procedure TForm1.ComboBox1Change(Sender: TObject);
begin
ShowMessage(PString(Combobox1.Items.Objects[0])^); //Hello world 1
end;
возникает ошибка (AV)
kyn66 (2009-11-16 16:39:00) [1]Да, прверил, вместо ShowMessage(IntToStr(AllocMemSize));заменил на Application.MessageBox(PChar(IntToStr(AllocMemSize)), PChar(''), MB_OK + MB_ICONASTERISK);и все стало на свои места. 12252=12252(до и после)
kyn66 (2009-11-16 16:31:00) [2]
> Как же - без разницы :)Измерять надо после первого ShowMessage.
Я так и измерял. После первого - 12252, после второго и последующего - 12284, даже не используя объекты(new/dispose)
> Ну, например, класс окна регистрируют не на один показ.
Вот может за счет этого и есть разница. И ею можно принебречь, я имею ввиду судя по данному тесту. Кстати, по совету [94] подключил FastMM, все настроил как показано в http://timokhov.blogspot.com/2007/03/delphi-2007-iii-fastmm.html. Инициализировал указатели и спецом их не уничтожая закрыл форму. Чегость утечки FastMM не показал. Хм, по консольному приложению из примера на сайте показывал.
Leonid Troyanovsky (2009-11-16 16:23:00) [3]
> kyn66 © (16.11.09 15:57) [101]
> >Попробуй повторить создание-разрушение дважды(без уничтожения
> >формы).
> Без разницы.
Как же - без разницы :)
Измерять надо после первого ShowMessage.
> kyn66 © (16.11.09 15:59) [102]
> Получается что ShowMessage внес изменения в память и при
> закрытии не подчистил за собой.
Ну, например, класс окна регистрируют не на один показ.
--
Regards, LVT.
Anatoly Podgoretsky (2009-11-16 16:17:00) [4]> kyn66 (16.11.2009 15:57:41) [101]
Вот и эта ветка уже за 100 постов.
kyn66 (2009-11-16 15:59:00) [5]Получается что ShowMessage внес изменения в память и при закрытии не подчистил за собой.
kyn66 (2009-11-16 15:57:00) [6]
> Leonid Troyanovsky © (16.11.09 15:36) [97]
>Попробуй повторить создание-разрушение дважды(без уничтожения >формы).
Без разницы. Как толькл открылась форма 12252. По пять раз создавал уничтожал - 12284. Однако заметил вот где. Открылась форма - смотрю память - 12252. Закрываю ShowMessage. Не создавая и не уничтожая объектов повторяю просмотр памяти - опс - 12284, еще и еще и еще смотрю память(объекты не трогаем) - 12284.
Дмитрий Белькевич (2009-11-16 15:41:00) [7]
> Попробуй повторить создание-разрушение дважды(без уничтожения
> формы).
А лучше без формы и, вообще, без VCL'а и без окон (в консольном приложении). VCL и Winapi много неявнях телодвижений с памятью делают.
Дмитрий Белькевич (2009-11-16 15:39:00) [8]Сразу же смотри FullDebugMode. Это дополнительно укажет двойное освобождение переменных.
Leonid Troyanovsky (2009-11-16 15:38:00) [9]
> Leonid Troyanovsky © (16.11.09 15:36) [97]
> память для регистрации класса.
В смысле: для регистрации класса окна.
--
Regards, LVT.
Leonid Troyanovsky (2009-11-16 15:36:00) [10]
> kyn66 © (16.11.09 13:58) [93]
> цикл и опять проверяю память - 14000, уничтожаю объекты
> с приведением - 12284. Хотя память не вернулась к числу
> начальному 12252(нужно разобраться почему).
Возможно, что, например, первый показ ShowMessage требует
память для регистрации класса.
Попробуй повторить создание-разрушение дважды
(без уничтожения формы).
--
Regards, LVT.
kyn66 (2009-11-16 15:17:00) [11]
> typeinfo, я так думаю, отдаётся разный и финализация происходит
> неверно.
Да действительно, Leonid Troyanovsky © (16.11.09 13:26) [92] уже это подчеркнул.
> В дополнение к экспериментам рекомендую использовать FastMM.
> Она сразу же утечки покажет.
Да, спасибо, сечас буду почитать про него.
Дмитрий Белькевич (2009-11-16 15:12:00) [12]>Хотя память не вернулась к числу начальному 12252(нужно разобраться почему)
Опять же - фрагментацию памяти не стоит забывать. Фрагментация памяти, кстати, одна из причин, по которой я бы не рекомендовал использовать New/Dispose. Если уж очень хочется извращаться - делай динамический массив записей и единомоментно (или 'чанками' по тысяче, если заранее неизвестен размер) устанавливай его размер. Это сильно уменьшит фрагментацию памяти и ускорит работу, иногда на порядок.
Дмитрий Белькевич (2009-11-16 14:57:00) [13]>Хотя память не вернулась к числу начальному 12252(нужно разобраться почему)
Кроме твоих записей может (и будет) создаваться разный самоуничтожаемый 'мусор'.
> Однако, когда я делаю уничтожение без приведения, память
> - 12460. Тоже не возвращается к начальному 12252
Смотри сырцы - найдёшь много интересного:
procedure _Dispose(p: Pointer; typeInfo: Pointer);
begin
_Finalize(p, typeinfo);
FreeMem(p);
end;
typeinfo, я так думаю, отдаётся разный и финализация происходит неверно.
В дополнение к экспериментам рекомендую использовать FastMM. Она сразу же утечки покажет.
kyn66 (2009-11-16 13:58:00) [14]
> А вот для удаления это важно, бо если компилятор не знает
> тип,то он и не вставит Finalize для очистки, скажем, строк.
Ага... решил мастера поймать... :) Дело в том, что я проверил еще одну ситуацию на коде из трех кнопок.
1) Запускает цикл с инициализацией переменной указателя, присваивает значения;
2) Удаление объектов:
3) Просто показывает память ShowMessage(IntToStr(AllocMemSize));
Так вот. Запускаю форму, проверяю память - 12252. Запускаю цикл и опять проверяю память - 14000, уничтожаю объекты с приведением - 12284. Хотя память не вернулась к числу начальному 12252(нужно разобраться почему). Однако, когда я делаю уничтожение без приведения, память - 12460. Тоже не возвращается к начальному 12252
procedure TForm1.Button2Click(Sender: TObject);
var
i:integer;
begin
for i:=0 to ListView1.Items.Count-1 do
Dispose({PMyRecord}(ListView1.Items[i].Data));
ListView1.Clear;
end;
Leonid Troyanovsky (2009-11-16 13:26:00) [15]
> kyn66 © (16.11.09 13:09) [91]
> и удаление можно выполнять без приведения?
А вот для удаления это важно, бо если компилятор не знает тип,
то он и не вставит Finalize для очистки, скажем, строк.
--
Regards, LVT.
kyn66 (2009-11-16 13:09:00) [16]Не дописал строку. Хотел сказать что в данном случае тогда и удаление можно выполнять без приведения? Какая разница что удалять?
if ListView1.Items[i].Data<> nil then
Dispose(ListView1.Items[i].Data);
kyn66 (2009-11-16 13:05:00) [17]
> Leonid Troyanovsky © (16.11.09 09:54) [84]
> if PMyRecord(ListView1.Items[i].Data)) <> nil
>Здесь приведение лишнее, бо загромождает суть.
Т.е. в данном случае важнее узнать есть ли там что либо для уничтожения и не важно какого типа?
if (ListView1.Items[i].Data) <> nil
sniknik (2009-11-16 11:35:00) [18]> В начале было New.
догадался... тема сбила "Строку в объект", как то больше в другим ассоциируется.
Демо (2009-11-16 11:33:00) [19]
> for i:=0 to ListView1.Items.Count-1 do
> Dispose(PMyRecord(ListView1.Items[i].Data));
> end;
Просто проверь - ссылается ли куда-то ListView1.Items[i].Data:
for i:=0 to ListView1.Items.Count-1 do
begin
if ListView1.Items[i].Data<> nil then Dispose(PMyRecord(ListView1.Items[i].Data));
end;
kyn66 (2009-11-16 10:26:00) [20]
> У блока нет имени, а есть адрес, скажем, его начала,
Пардонс, не так выразился. Конечно же адрес(имелось ввиду имя переменной для конкретнокго адреса блока памяти). Информации предостаточно. Большое спасибо всем мастерам за разъяснения и толерантность.