Страница 1 из 2
Правильное уничтожение созданных в рантайме объектов?
Добавлено: 13.07.2012 10:16:10
OberonAR
День добрый!
Подскажите по сабжу пожалуйста. Конкретный пример.
1) У меня в проекте есть функция (прописана в отдельном модуле) получения значения поля из определенной таблицы бд MySQL. Внутри нее я создаю
Код: Выделить всё
var query : TZReadOnlyQuery;
begin
query:=TZReadOnlyQuery.Create(application);
query.Connection:=DataModule1.ZConnection1;
.
.
.
{уничтожаю так:}
query.Close;
query:=nil;
query.Free;
end;
Функция эта вызывается довольно много раз. И каждый раз после ее вызова я наблюдаю в диспетчере процессов как мое приложение отхапывает себе кусок памяти 300-1000 кб и не освобождает ее. Подозреваю что уничтожаю query неправильно.
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 13.07.2012 10:35:52
Mr.Smart
Если вы загляните в метод
Free, то увидите следующее:
Код: Выделить всё
procedure TObject.Free;
begin
// the call via self avoids a warning
if self<>nil then
self.destroy;
end;
после ваших действий
query:=nil; Self равен nil и уничтожение объекта не происходит.
Выкиньте нафиг строчку с
query:=nil;!!!
з.ы. Интересно узнать, кто вас научил так уничтожать объекты?
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 13.07.2012 10:48:20
Brainenjii
По теме - лучше будет, наверное, так -
Код: Выделить всё
var query : TZReadOnlyQuery;
begin
query:=TZReadOnlyQuery.Create(application);
query.Connection:=DataModule1.ZConnection1;
.
.
.
{уничтожаю так:}
query.Close;
FreeAndNil(query);
end;
Не по теме - зачем такая штука как Free? Только же прятать ошибки в алгоритме - пытаться уничтожить отсутствующий объект это же явная ошибка. А если напрямую Destroy'ем - хоть сразу исключение поднимается...
Просто я всегда вызываю деструктор напрямую - может я допускаю какую-то ошибку и чего-то не знаю?
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 13.07.2012 10:50:41
SSerge
Mr.Smart писал(а):з.ы. Интересно узнать, кто вас научил так уничтожать объекты?
это копипаста с JAVA/C#, там принято присваивать указателю на экземпляр null, якобы это заставляет шевелиться сборщик мусора и объект уничтожать.
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 13.07.2012 11:01:23
Sergei I. Gorelkin
Brainenjii писал(а):Просто я всегда вызываю деструктор напрямую - может я допускаю какую-то ошибку и чего-то не знаю?
Например, при возникновении исключения в конструкторе деструктор вызывается для недосозданного объекта, если у этого объекта есть поля-объекты, то они могут быть равны nil.
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 13.07.2012 11:18:08
Brainenjii
хм... Не знал, что при исключении в конструкторе неявно вызывается деструктор. Или я Вас не правильно понял и Вы просто об освобождении "недосозданного" объекта?... Вообще, стараюсь не допускать возможности поднятия исключений на этапе инициализации. Кроме этого - есть ли ещё какие-то ситуации, когда вызов Destroy напрямую "хуже" Free?
В любом случае, ИМХО, если есть сомнения, то лучше проверить - был ли создан объект перед его разрушением явно. К тому же, Free допускает только одно имя у деструктора, хотя, к счастью, в паскале давать имена конструкторам/деструкторам можно произвольные ^_^
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 13.07.2012 11:44:34
Sergei I. Gorelkin
Все правильно поняли, деструктор вызывается неявно при исключении в конструкторе (и до кучи, в методе AfterConstruction).
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 13.07.2012 12:18:37
debi12345
По-параноидальному, с перестраховками (также на случай аварийного выхода программы,..):
Код: Выделить всё
result:= OK;
QueryVar:= nil;
try
QueryVar:= QueryType.Create(..);
try
[...]
QueryVar.Active:= true;
except
on e:EDatabaseError do begin
result:= FAILED;
ShowMessage('Smth wrong');
exit;
end;
[..]
end;
finally
if QueryVar <> nil then begin
QueryVar.Active:= false;
FreeAndNil(QueryVar);
end;
end;
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 14.07.2012 10:27:14
OberonAR
FreeAndNil(Query) вызывает исключение доступа к памяти... Хотя вчера вечером FreeAndNil(Query) работало без исключений, но и память не освобождало. Ничего не пойму.
Вот вчерашний вариант функции, который сегодня вызывает исключение:
Код: Выделить всё
function get_value_from_bd (table : integer; id : string; pole : string) : string;
var query : TZReadOnlyQuery; s1,s2 : string;
begin
if id='' then id:='0';
query:=TZReadOnlyQuery.Create(application);
query.Connection:=DataModule1.ZConnection1;
query.SQL.Clear;
query.SQL.Add('SELECT s_tables.`table`, s_tables.id_table FROM s_tables WHERE s_tables.id_s_tables = '+inttostr(table));
query.Open;
s1:=query.FieldByName('table').AsString;
s2:=query.FieldByName('id_table').AsString;
query.Close;
query.SQL.Clear;
query.SQL.Add('SELECT '+s1+'.'+pole+' FROM '+s1+' WHERE '+s1+'.'+s2+' = '+id);
query.Open;
get_value_from_bd:=query.FieldByName(pole).AsString;
query.Close;
Query.Active:= false;
FreeAndNil(Query);
end;
с просто query.free работает, но тоже не освобождает память...
Дополнение.
В этом же модуле есть другая ф-я, которая создает заранее подготовленную форму (из автосоздания убрана) и также создает TZQuery как и выше описано. что форму, что query удаляю FreeAndNil("имя переменной"). Так вот в этой ф-ии все работает без исключений, но опять же не освобождается память.
Добавлено спустя 39 минут 39 секунд:OberonAR писал(а):с просто query.free работает, но тоже не освобождает память...
не, не работает, на любую попытку free ошибка доступа. Блин, ну вчера же работало без исключений. Ничего не понимяю

Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 14.07.2012 15:02:33
debi12345
FreeAndNil(Query) вызывает исключение доступа к памяти
Перед его вызовом желательно проверять переменную на "<> nil".
с просто query.free работает, но тоже не освобождает память...
Пишите багрепорт по поводу MEMORY LEAK команде ZEOS.
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 14.07.2012 15:28:28
OberonAR
debi12345 писал(а): с просто query.free работает, но тоже не освобождает память...
Пишите багрепорт по поводу MEMORY LEAK команде ZEOS.
Нет, не работает query.free, я ошибся. с TForm работает и FreeAndNil даже память очищает, но только пытаешься сделать FreeAndNil для переменной TZQuery (ZEOS), сразу исключение...
Может это у меня какие настройки слетели?
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 14.07.2012 16:25:10
debi12345
но только пытаешься сделать FreeAndNil для переменной TZQuery (ZEOS),
на NIL перед FREE проверяете ?
Добавлено спустя 1 минуту 30 секунд:Или все же фатальный сбой типа AcessViolation или SegmentainFault ?
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 14.07.2012 17:23:59
OberonAR
debi12345 писал(а):Или все же фатальный сбой типа AcessViolation или SegmentainFault ?
AcessViolation
правда на nil не проверял в этот раз.
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 14.07.2012 18:18:56
debi12345
правда на nil не проверял в этот раз.
Почему ?
Никогда не помешает перед созданием экзмепляра объекта присвоить объектной перремнной NIL, а перед освобождением экземпляра - проверить объектную переменную на NIL. Это убережет от фатальных ошибок, связанных с несозданием объекта (если такое возможно в принципе - ошибки в коде создания, нехватка памяти,..).
Re: Правильное уничтожение созданных в рантайме объектов?
Добавлено: 14.07.2012 19:04:56
alexey38
Судя по всему исключение при уничтожении самого объекта (попробуйте посмотреть в отладчике, шагнув внутрь).
А функция Free и так проверяет на NIL перед Destroy, см. самое первое сообщение, где было вначале присоваивание NIL а потом FREE, и была только утечка памяти.