Правильное уничтожение созданных в рантайме объектов?

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Правильное уничтожение созданных в рантайме объектов?

Сообщение OberonAR » 13.07.2012 10:16:10

День добрый!
Подскажите по сабжу пожалуйста. Конкретный пример.
1) У меня в проекте есть функция (прописана в отдельном модуле) получения значения поля из определенной таблицы бд MySQL. Внутри нее я создаю
Код: Выделить всё
var query : TZReadOnlyQuery;
begin

query:=TZReadOnlyQuery.Create(application);
query.Connection:=DataModule1.ZConnection1;
.
.
.
{уничтожаю так:}
query.Close;

query:=nil;
query.Free;
end;


Функция эта вызывается довольно много раз. И каждый раз после ее вызова я наблюдаю в диспетчере процессов как мое приложение отхапывает себе кусок памяти 300-1000 кб и не освобождает ее. Подозреваю что уничтожаю query неправильно.
Аватара пользователя
OberonAR
новенький
 
Сообщения: 73
Зарегистрирован: 08.02.2012 11:46:04
Откуда: Краснодарский край

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение Mr.Smart » 13.07.2012 10:35:52

Код: Выделить всё
query:=nil;
query.Free;

:?: :?: :?:
Если вы загляните в метод 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;!!!

з.ы. Интересно узнать, кто вас научил так уничтожать объекты?
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение Brainenjii » 13.07.2012 10:48:20

По теме - лучше будет, наверное, так -
Код: Выделить всё
var query : TZReadOnlyQuery;
begin

query:=TZReadOnlyQuery.Create(application);
query.Connection:=DataModule1.ZConnection1;
.
.
.
{уничтожаю так:}
query.Close;

FreeAndNil(query);
end;

Не по теме - зачем такая штука как Free? Только же прятать ошибки в алгоритме - пытаться уничтожить отсутствующий объект это же явная ошибка. А если напрямую Destroy'ем - хоть сразу исключение поднимается...
Просто я всегда вызываю деструктор напрямую - может я допускаю какую-то ошибку и чего-то не знаю?
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение SSerge » 13.07.2012 10:50:41

Mr.Smart писал(а):з.ы. Интересно узнать, кто вас научил так уничтожать объекты?


это копипаста с JAVA/C#, там принято присваивать указателю на экземпляр null, якобы это заставляет шевелиться сборщик мусора и объект уничтожать.
SSerge
энтузиаст
 
Сообщения: 971
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение Sergei I. Gorelkin » 13.07.2012 11:01:23

Brainenjii писал(а):Просто я всегда вызываю деструктор напрямую - может я допускаю какую-то ошибку и чего-то не знаю?


Например, при возникновении исключения в конструкторе деструктор вызывается для недосозданного объекта, если у этого объекта есть поля-объекты, то они могут быть равны nil.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение Brainenjii » 13.07.2012 11:18:08

хм... Не знал, что при исключении в конструкторе неявно вызывается деструктор. Или я Вас не правильно понял и Вы просто об освобождении "недосозданного" объекта?... Вообще, стараюсь не допускать возможности поднятия исключений на этапе инициализации. Кроме этого - есть ли ещё какие-то ситуации, когда вызов Destroy напрямую "хуже" Free?
В любом случае, ИМХО, если есть сомнения, то лучше проверить - был ли создан объект перед его разрушением явно. К тому же, Free допускает только одно имя у деструктора, хотя, к счастью, в паскале давать имена конструкторам/деструкторам можно произвольные ^_^
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение Sergei I. Gorelkin » 13.07.2012 11:44:34

Все правильно поняли, деструктор вызывается неявно при исключении в конструкторе (и до кучи, в методе AfterConstruction).
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение debi12345 » 13.07.2012 12:18:37

По-параноидальному, с перестраховками (также на случай аварийного выхода программы,..):

Код: Выделить всё
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;
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение OberonAR » 14.07.2012 09:47:35

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 ошибка доступа. Блин, ну вчера же работало без исключений. Ничего не понимяю :cry:
Аватара пользователя
OberonAR
новенький
 
Сообщения: 73
Зарегистрирован: 08.02.2012 11:46:04
Откуда: Краснодарский край

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение debi12345 » 14.07.2012 15:02:33

FreeAndNil(Query) вызывает исключение доступа к памяти

Перед его вызовом желательно проверять переменную на "<> nil".

с просто query.free работает, но тоже не освобождает память...

Пишите багрепорт по поводу MEMORY LEAK команде ZEOS.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение OberonAR » 14.07.2012 15:28:28

debi12345 писал(а): с просто query.free работает, но тоже не освобождает память...


Пишите багрепорт по поводу MEMORY LEAK команде ZEOS.


Нет, не работает query.free, я ошибся. с TForm работает и FreeAndNil даже память очищает, но только пытаешься сделать FreeAndNil для переменной TZQuery (ZEOS), сразу исключение...

Может это у меня какие настройки слетели?
Аватара пользователя
OberonAR
новенький
 
Сообщения: 73
Зарегистрирован: 08.02.2012 11:46:04
Откуда: Краснодарский край

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение debi12345 » 14.07.2012 16:23:40

но только пытаешься сделать FreeAndNil для переменной TZQuery (ZEOS),

на NIL перед FREE проверяете ?

Добавлено спустя 1 минуту 30 секунд:
Код: Выделить всё
сразу исключение...

Или все же фатальный сбой типа AcessViolation или SegmentainFault ?
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение OberonAR » 14.07.2012 17:23:59

debi12345 писал(а):Или все же фатальный сбой типа AcessViolation или SegmentainFault ?


AcessViolation
правда на nil не проверял в этот раз.
Аватара пользователя
OberonAR
новенький
 
Сообщения: 73
Зарегистрирован: 08.02.2012 11:46:04
Откуда: Краснодарский край

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение debi12345 » 14.07.2012 18:18:56

правда на nil не проверял в этот раз.

Почему ?
Никогда не помешает перед созданием экзмепляра объекта присвоить объектной перремнной NIL, а перед освобождением экземпляра - проверить объектную переменную на NIL. Это убережет от фатальных ошибок, связанных с несозданием объекта (если такое возможно в принципе - ошибки в коде создания, нехватка памяти,..).
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5759
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Правильное уничтожение созданных в рантайме объектов?

Сообщение alexey38 » 14.07.2012 19:04:56

Судя по всему исключение при уничтожении самого объекта (попробуйте посмотреть в отладчике, шагнув внутрь).
А функция Free и так проверяет на NIL перед Destroy, см. самое первое сообщение, где было вначале присоваивание NIL а потом FREE, и была только утечка памяти.
alexey38
долгожитель
 
Сообщения: 1627
Зарегистрирован: 27.04.2011 19:42:31

След.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8

Рейтинг@Mail.ru