Форум: "Начинающим";
Текущий архив: 2010.01.10;
Скачать: [xml.tar.bz2];
ВнизСтроку в объект Найти похожие ветки
← →
sniknik © (2009-11-16 09:30) [80]> Dispose(PMyRecord(ListView1.Items[i].Data));
PMyRecord(ListView1.Items[i].Data).Free;
← →
Юрий Зотов © (2009-11-16 09:30) [81]> kyn66 © (16.11.09 09:24) [78]
> Получается так, что если память выделена, то ее обязательно нужно
> чем-то заполнить.
Заполнять не обязательно. Обязательно другое - помнить адрес выделенного блока, чтобы потом можно было его освободить.
Похоже, Вы пока еще немного путаетесь. Есть АДРЕС выделенного блока, а есть СОДЕРЖИМОЕ этого блока. Это совершенно разные вещи. Адрес хранится в переменной типа "указатель", а содержимое хранится в самом блоке.
← →
sniknik © (2009-11-16 09:33) [82]а ну да, если у тебя там "дыры" то значит повторное использование тоже будет. значит
FreeAndNil(PMyRecord(ListView1.Items[i].Data));
← →
Leonid Troyanovsky © (2009-11-16 09:47) [83]
> sniknik © (16.11.09 09:30) [80]
В начале было New.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2009-11-16 09:54) [84]
> kyn66 © (16.11.09 09:24) [78]
> if PMyRecord(ListView1.Items[i].Data)) <> nil
Здесь приведение лишнее, бо загромождает суть.
--
Regards, LVT.
← →
kyn66 © (2009-11-16 10:03) [85]
> Заполнять не обязательно. Обязательно другое - помнить адрес
> выделенного блока, чтобы потом можно было его освободить.
>
Но в данном случае (заполнение в цикле) переменная инициализируется, получает/не получает значение, инициализируется на новый блок памяти. И имя переменной, связанной с конкретным блоком мы как таковое теряем. Т.е. к конкретному блоку по имени мы обратиться не сможем. Поэтому мы в цикле пробегаем по всем итемам и удаляем, если что то там есть
for i:=0 to ListView1.Items.Count-1 do
Dispose(PMyRecord(ListView1.Items[i].Data));
end;
> Есть АДРЕС выделенного блока, а есть СОДЕРЖИМОЕ этого блока.
> Это совершенно разные вещи. Адрес хранится в переменной
> типа "указатель", а содержимое хранится в самом блоке.
Не, с этим похоже разобрался уже.
← →
Leonid Troyanovsky © (2009-11-16 10:11) [86]
> kyn66 © (16.11.09 10:03) [85]
> блок памяти. И имя переменной, связанной с конкретным блоком
> мы как таковое теряем. Т.е. к конкретному блоку по имени
> мы обратиться не сможем. Поэтому мы в цикле пробегаем по
> всем итемам и удаляем, если что то там есть
У блока нет имени, а есть адрес, скажем, его начала,
который хранят в к.л. переменной (ну, и размер блока).
В какой переменной - это на усмотрение программиста.
Как это делать правильно тебе уже объясняли.
--
Regards, LVT.
← →
kyn66 © (2009-11-16 10:26) [87]
> У блока нет имени, а есть адрес, скажем, его начала,
Пардонс, не так выразился. Конечно же адрес(имелось ввиду имя переменной для конкретнокго адреса блока памяти). Информации предостаточно. Большое спасибо всем мастерам за разъяснения и толерантность.
← →
Демо © (2009-11-16 11:33) [88]
> 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;
← →
sniknik © (2009-11-16 11:35) [89]> В начале было New.
догадался... тема сбила "Строку в объект", как то больше в другим ассоциируется.
← →
kyn66 © (2009-11-16 13:05) [90]
> Leonid Troyanovsky © (16.11.09 09:54) [84]
> if PMyRecord(ListView1.Items[i].Data)) <> nil
>Здесь приведение лишнее, бо загромождает суть.
Т.е. в данном случае важнее узнать есть ли там что либо для уничтожения и не важно какого типа?
if (ListView1.Items[i].Data) <> nil
← →
kyn66 © (2009-11-16 13:09) [91]Не дописал строку. Хотел сказать что в данном случае тогда и удаление можно выполнять без приведения? Какая разница что удалять?
if ListView1.Items[i].Data<> nil then
Dispose(ListView1.Items[i].Data);
← →
Leonid Troyanovsky © (2009-11-16 13:26) [92]
> kyn66 © (16.11.09 13:09) [91]
> и удаление можно выполнять без приведения?
А вот для удаления это важно, бо если компилятор не знает тип,
то он и не вставит Finalize для очистки, скажем, строк.
--
Regards, LVT.
← →
kyn66 © (2009-11-16 13:58) [93]
> А вот для удаления это важно, бо если компилятор не знает
> тип,то он и не вставит 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;
← →
Дмитрий Белькевич (2009-11-16 14:57) [94]>Хотя память не вернулась к числу начальному 12252(нужно разобраться почему)
Кроме твоих записей может (и будет) создаваться разный самоуничтожаемый "мусор".
> Однако, когда я делаю уничтожение без приведения, память
> - 12460. Тоже не возвращается к начальному 12252
Смотри сырцы - найдёшь много интересного:
procedure _Dispose(p: Pointer; typeInfo: Pointer);
begin
_Finalize(p, typeinfo);
FreeMem(p);
end;
typeinfo, я так думаю, отдаётся разный и финализация происходит неверно.
В дополнение к экспериментам рекомендую использовать FastMM. Она сразу же утечки покажет.
← →
Дмитрий Белькевич (2009-11-16 15:12) [95]>Хотя память не вернулась к числу начальному 12252(нужно разобраться почему)
Опять же - фрагментацию памяти не стоит забывать. Фрагментация памяти, кстати, одна из причин, по которой я бы не рекомендовал использовать New/Dispose. Если уж очень хочется извращаться - делай динамический массив записей и единомоментно (или "чанками" по тысяче, если заранее неизвестен размер) устанавливай его размер. Это сильно уменьшит фрагментацию памяти и ускорит работу, иногда на порядок.
← →
kyn66 © (2009-11-16 15:17) [96]
> typeinfo, я так думаю, отдаётся разный и финализация происходит
> неверно.
Да действительно, Leonid Troyanovsky © (16.11.09 13:26) [92] уже это подчеркнул.
> В дополнение к экспериментам рекомендую использовать FastMM.
> Она сразу же утечки покажет.
Да, спасибо, сечас буду почитать про него.
← →
Leonid Troyanovsky © (2009-11-16 15:36) [97]
> kyn66 © (16.11.09 13:58) [93]
> цикл и опять проверяю память - 14000, уничтожаю объекты
> с приведением - 12284. Хотя память не вернулась к числу
> начальному 12252(нужно разобраться почему).
Возможно, что, например, первый показ ShowMessage требует
память для регистрации класса.
Попробуй повторить создание-разрушение дважды
(без уничтожения формы).
--
Regards, LVT.
← →
Leonid Troyanovsky © (2009-11-16 15:38) [98]
> Leonid Troyanovsky © (16.11.09 15:36) [97]
> память для регистрации класса.
В смысле: для регистрации класса окна.
--
Regards, LVT.
← →
Дмитрий Белькевич (2009-11-16 15:39) [99]Сразу же смотри FullDebugMode. Это дополнительно укажет двойное освобождение переменных.
← →
Дмитрий Белькевич (2009-11-16 15:41) [100]
> Попробуй повторить создание-разрушение дважды(без уничтожения
> формы).
А лучше без формы и, вообще, без VCL"а и без окон (в консольном приложении). VCL и Winapi много неявнях телодвижений с памятью делают.
← →
kyn66 © (2009-11-16 15:57) [101]
> Leonid Troyanovsky © (16.11.09 15:36) [97]
>Попробуй повторить создание-разрушение дважды(без уничтожения >формы).
Без разницы. Как толькл открылась форма 12252. По пять раз создавал уничтожал - 12284. Однако заметил вот где. Открылась форма - смотрю память - 12252. Закрываю ShowMessage. Не создавая и не уничтожая объектов повторяю просмотр памяти - опс - 12284, еще и еще и еще смотрю память(объекты не трогаем) - 12284.
← →
kyn66 © (2009-11-16 15:59) [102]Получается что ShowMessage внес изменения в память и при закрытии не подчистил за собой.
← →
Anatoly Podgoretsky © (2009-11-16 16:17) [103]> kyn66 (16.11.2009 15:57:41) [101]
Вот и эта ветка уже за 100 постов.
← →
Leonid Troyanovsky © (2009-11-16 16:23) [104]
> kyn66 © (16.11.09 15:57) [101]
> >Попробуй повторить создание-разрушение дважды(без уничтожения
> >формы).
> Без разницы.
Как же - без разницы :)
Измерять надо после первого ShowMessage.
> kyn66 © (16.11.09 15:59) [102]
> Получается что ShowMessage внес изменения в память и при
> закрытии не подчистил за собой.
Ну, например, класс окна регистрируют не на один показ.
--
Regards, LVT.
← →
kyn66 © (2009-11-16 16:31) [105]
> Как же - без разницы :)Измерять надо после первого ShowMessage.
Я так и измерял. После первого - 12252, после второго и последующего - 12284, даже не используя объекты(new/dispose)
> Ну, например, класс окна регистрируют не на один показ.
Вот может за счет этого и есть разница. И ею можно принебречь, я имею ввиду судя по данному тесту. Кстати, по совету [94] подключил FastMM, все настроил как показано в http://timokhov.blogspot.com/2007/03/delphi-2007-iii-fastmm.html . Инициализировал указатели и спецом их не уничтожая закрыл форму. Чегость утечки FastMM не показал. Хм, по консольному приложению из примера на сайте показывал.
← →
kyn66 © (2009-11-16 16:39) [106]Да, прверил, вместо ShowMessage(IntToStr(AllocMemSize)); заменил на Application.MessageBox(PChar(IntToStr(AllocMemSize)), PChar(""), MB_OK + MB_ICONASTERISK); и все стало на свои места. 12252=12252(до и после)
Страницы: 1 2 3 вся ветка
Форум: "Начинающим";
Текущий архив: 2010.01.10;
Скачать: [xml.tar.bz2];
Память: 0.66 MB
Время: 0.01 c