Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Освобождение ресурса в finally


Страницы:   1 2 ... 15 16 17 18 19 20 21 ... 32 33

Arinyshka ©   (2008-04-23 12:17:00) 

Не подскажете еще один момент:
Есть процедура, выглядит примерно так

procedure TSetPayFrm.BtnAddImageClick(Sender: TObject);
var  TempBitmap:TBitmap;
begin
if not(opendialog1.Execute) then  exit;
try
 TempBitmap  := TBitmap.Create;
 TempBitmap.LoadFromFile(OpenDialog1.FileName);
finally
TempBitmap.Free;
end;
end;

На освобождение  TempBitmap.Free; выдает варнинг
[Warning] uSetPaymentMain.pas(313): Variable 'TempBitmap' might not have been initialized
Не смертельно, но непонятно... почему варнинг? При изменениии условия и включении всей конструкции в один блок begin..end ситуация не менялась.


Экс-Оригинал   (2008-04-27 15:39:00) [341]


> Leonid Troyanovsky ©   (27.04.08 10:28) [286]


По поводу кода 4:
Delphi 6:
 function ReadCustomVariant: Variant;
 var
   OuterStream, InnerStream: TMemoryStream;
   OuterReader: TReader;
   StreamSize: Integer;
   CustomType: TCustomVariantType;
   CustomTypeClassName: string;
   VarStreamer: IVarStreamable;
 begin
   CheckValue(vaBinary);
   OuterStream := TMemoryStream.Create;
   InnerStream := TMemoryStream.Create;
   try
     Read(StreamSize, SizeOf(StreamSize));
     OuterStream.Size := StreamSize;
     Read(OuterStream.Memory^, StreamSize);

     OuterReader := TReader.Create(OuterStream, 1024);
     try
       CustomTypeClassName := OuterReader.ReadString;
       OuterReader.Read(StreamSize, SizeOf(StreamSize));
       InnerStream.Size := StreamSize;
       OuterReader.Read(InnerStream.Memory^, StreamSize);

       if not FindCustomVariantType(CustomTypeClassName, CustomType) or
          not Supports(TObject(CustomType), IVarStreamable, VarStreamer) then
         raise EReadError.CreateRes(@SReadError);
       TVarData(Result).VType := CustomType.VarType;
       VarStreamer.StreamIn(TVarData(Result), InnerStream);
     finally
       OuterReader.Free;
     end;
   finally
     InnerStream.Free;
     OuterStream.Free;
   end;
 end;


BDS2006:

 function ReadCustomVariant: Variant;
 var
   OuterStream, InnerStream: TMemoryStream;
   OuterReader: TReader;
   StreamSize: Integer;
   CustomType: TCustomVariantType;
   CustomTypeClassName: string;
   VarStreamer: IVarStreamable;
 begin
   CheckValue(vaBinary);

   InnerStream := nil;
   OuterStream := TMemoryStream.Create;
   try
     InnerStream := TMemoryStream.Create;

     Read(StreamSize, SizeOf(StreamSize));
     OuterStream.Size := StreamSize;
     Read(OuterStream.Memory^, StreamSize);

     OuterReader := TReader.Create(OuterStream, 1024);
     try
       CustomTypeClassName := OuterReader.ReadString;
       OuterReader.Read(StreamSize, SizeOf(StreamSize));
       InnerStream.Size := StreamSize;
       OuterReader.Read(InnerStream.Memory^, StreamSize);

       if not FindCustomVariantType(CustomTypeClassName, CustomType) or
          not Supports(CustomType, IVarStreamable, VarStreamer) then
         raise EReadError.CreateRes(@SReadError);
       TVarData(Result).VType := CustomType.VarType;
       VarStreamer.StreamIn(TVarData(Result), InnerStream);
     finally
       OuterReader.Free;
     end;
   finally
     InnerStream.Free;
     OuterStream.Free;
   end;
 end;


В первом случае потерян один try..finally - утечка памяти.
Если добавить, код будет менее прозрачным.

Во втором случае всё наглядно.


Игорь Шевченко   (2008-04-27 14:57:00) [342]

Расстрелять и дело с концом


Восхищенный   (2008-04-27 14:42:00) [343]

> Loginov Dmitry ©   (27.04.08 14:31) [309]

> А статья была написана с целью помочь начинающему в освоении и
> понимании try..finally,

И, желая помочь начинающемув пониманииtry..finally, ты пишешь вот такой страшный пример (кстати, четко показывающий, что ты и сам толком не понимаешь того, о чем пишешь). А этот бедняга начинающий, не в состоянии даже понять, что пример страшный, и думает, что так и надо делать.

Выглядишь ты при этом довольно смешно, но не это главное. Главное вот что - ты понимаешь, что совершаешь почти преступление?


Loginov Dmitry   (2008-04-27 14:31:00) [344]

> Зачем нужны клоны трудов Архангельского


Кстати, Архангельский в одном из источников некорректно описывал спицифику работы с try..finally, а из-за этого я долгое время пренебрегал использованием данного оператора, и извращался с try..except. А статья была написана с целью помочь начинающемув освоении и понимании try..finally, поскольку достаточные объяснения приводятся далеко не каждым автором. Статья свою работу, считаю, делает, так зачем ее удалять? Нужно ее просто доработать с учетом всех накопленных с того момента знаний.


Loginov Dmitry   (2008-04-27 14:07:00) [345]

> Не писал бы ты...Зачем нужны клоны трудов Архангельского
> ?


По хорошему удалить ее следует. Но жалко :(


Экс-Оригинал   (2008-04-27 13:58:00) [346]


> Loginov Dmitry ©   (27.04.08 13:24) [304]
> Опустили Вы меня (и не только :),
>  аж не по себе стало!Я даже по такому случаю статейку ту
> перепишу, чтоб не позориться :)


Просто нужно различать, где возможно использовать такие методы, а где нельзя.
Догмы - не руководство к действию.
Есть некие правила построения кода, но они должны быть действительно логичными и доказанными.
Если некто утверждает категорично, что делать нужно только так, потому что только так правильно - его можно даже не слушать, пока не будет доказательств.

Правило может действовать в общем случае. В частном же бывает, что можно сделать лучше, нарушая его.
Для этого нужны всего лишь знания.


Экс-Оригинал   (2008-04-27 13:54:00) [347]

Если говорить о конкретных случаях при создании нескольких объектов, то, зная, как они должны работать, как работают конструкторы, возможные исключения, - не вижу никакого доказательства невозможности конструкции с дополнительными присваиваниями.

Хотелось бы поверить, что это неправильно ВО ВСЕХ случаях, но не могу принять на веру, так как не вижу смысла слепо верить авторитетам, тем более слушать анонимные безапелляционные высказывания.

Пока из всего вышесказанного видно, что в некоторых случаях (если не знать внутреннй реализации до тонкостей) конструкция с дополнительным присваиванием может быть неустойчивой к исключениям. но это только лишь В НЕКОТОРЫХ случаях.

Вряд ли стоит индуцировать отдельный пример в закономерность.

Это тоже самое, что сказать - вот в этом случае GOTO плохо. Значит, плохо везде.


Игорь Шевченко   (2008-04-27 13:31:00) [348]


> Я даже по такому случаю статейку ту перепишу, чтоб не позориться
> :)


Не писал бы ты...Зачем нужны клоны трудов Архангельского ?


Loginov Dmitry   (2008-04-27 13:24:00) [349]

> В твоем примере любой профи, даже вдрызг пьяный, автоматически
> и не задумываясь написал бы try на 3 строки выше. Автопилот
> срабатывает.


Ну ладно. Опустили Вы меня (и не только :), аж не по себе стало!
Я даже по такому случаю статейку ту перепишу, чтоб не позориться :)


Восхищенный   (2008-04-27 13:06:00) [350]

> Loginov Dmitry ©   (27.04.08 12:09) [297]

> "Профи же, наученные горьким опытом" - такие вообще существуют

Существуют, и очень много. Здесь они тоже есть, и тоже немало. Ты их тоже видишь, просто пока не понимаешь их действительного уровня.

> Как вообще может произойти ошибка в таких безобидных конструкторах,
> как TDataBase.Create, TQuery.Create, TList.Create, TStringList.Create,
> TMemoryStream.Create если ее намеренно не спровоцировать?

Вот ты сам и привел пример дилетантских рассуждений "этого не случится, потому что вероятность этого слишком мала и потому что в моей практике такого не случалось".

"Может быть, не может быть, одна миллионная, мало, много..." Профи подобными вопросами даже не заморачиваются, они на автопилоте пишут код так, чтобы он работал и при своей ошибке, и при чужой ошибке, и при любом коде конструктора, и при всем остальном, и сегодня, и завтра, и после внесения изменений.

В твоем примере любой профи, даже вдрызг пьяный, автоматически и не задумываясь написал бы try на 3 строки выше. Автопилот срабатывает.


Loginov Dmitry   (2008-04-27 12:54:00) [351]

> например рядом крутящийся поток пишущий в неверную область
> памяти


Очень часто это приводит к краху программы, и мало вероятности, что try..finally от этого сможет спасти. К чему спасать, если программа дальше не сможет работать корректно? Запись в неверную область памяти - это программная ошибка, которую исправлять надо.


> стараясь спасти ситуацию. приложению ведь еще и дальше работать.


Кратко и убедительно!


> [299] Palladin ©   (27.04.08 12:35)
>
> >конструктор для нас темная лошадка.
>
> извиняюсь, не договорил,
>
> темная лошадка. сегодня он безобидный, завтра преопаснейший.
> и мы имеем огромную кучу проблем и мемликов.


Если сегодя какой-нибудь TList.Create безопасный, а завтра - преопаснейший, то какой толк от всех этих try..finally, если программа работать не сможет? ;) Хотя то, что при этом не будет никаких утечек памяти - это конечно круто!

Хотя в принципе и такое возможно. Действительно, если класс не такой примитивный, как TList (например, тот же TDataBase / TQuery), то еще неизвестно, как конструктор себя поведет, если на компьютере не инсталлирован необходимый для его работы софт, а приложение должно работать в любом случае...

Ладно! Основную идею понял! Убедили! Спасибо!


Anatoly Podgoretsky   (2008-04-27 12:52:00) [352]

> {RASkov}  (27.04.2008 12:37:00)  [300]

В трансе наверно Дмитрий глаза открыли - откуда дети берутся.


{RASkov}   (2008-04-27 12:37:00) [353]

:)
Аринушка наверное в трансе)


Palladin   (2008-04-27 12:35:00) [354]


>конструктор для нас темная лошадка.

извиняюсь, не договорил,

темная лошадка. сегодня он безобидный, завтра преопаснейший. и мы имеем огромную кучу проблем и мемликов.


Palladin   (2008-04-27 12:29:00) [355]


>Как вообще может произойти ошибка в таких безобидных конструкторах, как
TDataBase.Create, TQuery.Create, TList.Create, TStringList.Create, TMemoryStream.Create

да очень просто, не нужно рассуждать так линейно. например рядом крутящийся поток пишущий в неверную область памяти, программа какого нибудь "кул хацкера" делающая WriteProcessMemory. все это угрожает стабильности приложения.

идеально стабильное - не существует, но приблизить его к идеалу мы можем. чем и занимаемся, грамотно выстраивая try finally и стараясь спасти ситуацию. приложению ведь еще и дальше работать.

это раз. два, откуда ты можешь знать, что происходит в конструкторе? (мы теперь не рассматриваем конкретные классы, а классы вообще) что там может вызваться, какое исключение сгенерироваться? конструктор для нас темная лошадка. и не нужно изобретать зоопарк из теорий построения кода в случае "безобидных" и в случае "опасных" конструкторов.


Loginov Dmitry   (2008-04-27 12:09:00) [356]

> Профи же, наученные горьким опытом, на "авось" никогда не
> рассчитывают, даже если вероятность ошибки 10e-6.


"Профи же, наученные горьким опытом" - такие вообще существуют, или это лишь теория?

Как вообще может произойти ошибка в таких безобидных конструкторах, как
TDataBase.Create, TQuery.Create, TList.Create, TStringList.Create, TMemoryStream.Create
если ее намеренно не спровоцировать?

Таким же макаром и в деструкторе может произойти ошибка, а в случае TDataBase и TQuery ошибка в деструкторе даже более вероятна, чем в конструкторе, тогда опять же есть риск утечки памяти.

10e-6 - очень большая цифра, означающая, что если в цикле миллион раз вызвать данный код, то в одном из конструкторов хотябы 1 раз произойдет AV.


Anatoly Podgoretsky   (2008-04-27 11:57:00) [357]

> Loginov Dmitry  (27.04.2008 11:30:54)  [294]

К простым, в случае ошибки, теряем от одного до дву Query и сам ADataBase
А вего то переместить try на три строки выше.


Восхищенный   (2008-04-27 11:53:00) [358]

> Loginov Dmitry ©   (27.04.08 11:30) [294]

Объясняю. Этот код - супердилетантский. Если на 2, 3 или 4 строке возникнет исключение, DataBase повиснет в памяти вместе с теми Query, которые успели создаться.

Типичный пример дилетантского подходе "этого не случится, потому что вероятность этого слишком мала и потому что в моей практике такого не случалось". Профи же, наученные горьким опытом, на "авось" никогда не рассчитывают, даже если вероятность ошибки 10e-6.

Сравни:

ADataBase := TDataBase.Create(nil);
try
 AQuery1 := TQuery.Create(ADataBase);
 AQuery2 := TQuery.Create(ADataBase);
 AQuery3 := TQuery.Create(ADataBase);
 ................................
finally
 ADataBase.Free;
end;

Вроде бы, тот же самый код - но без риска утечки памяти.


Loginov Dmitry   (2008-04-27 11:30:00) [359]

> Потому что это не код, а целенаправленая диверсия.


Анатолий, объясните Вы хоть, в чем тут заключается диверсия? Почему целенаправленная?
К каким потенциальным проблемам может привести подобный код?


Anatoly Podgoretsky   (2008-04-27 11:22:00) [360]

Потому что это не код, а целенаправленая диверсия.


Страницы:   1 2 ... 15 16 17 18 19 20 21 ... 32 33

Наверх

Титульная страница Поиск, карта сайта Написать письмо