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

Вопросы программирования и использования среды Lazarus.

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

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

Сообщение sunjob » 19.04.2022 19:17:12

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

Код: Выделить всё
begin
var ResponceStream := PostRequest(UrlCtrl + '/api/hello', PostSource);
try
// here void
finally
  ResponceStream.Free;
  end;
end;

задал вопрос автору:
смысл использовать т.о. try-finally?
если что-то случаться в процессе отправки запроса, то не произойдет "дефолтного" освобождения рессурса

получил ответ:
наоборот обязательно произойдет освобождение


поясните, почему? :о)

небольшая ремарка: данный код из Delphi-проекта, переношу на Lazarus

спасибо!
Аватара пользователя
sunjob
постоялец
 
Сообщения: 156
Зарегистрирован: 12.01.2011 15:19:54

Re: try-finally - освобождение ресурса

Сообщение Shleps » 19.04.2022 20:48:14

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

А там написано //void
От чего защищаемся то?

И от такого объявления меня коробит.
var ResponceStream := PostRequest(UrlCtrl + '/api/hello', PostSource);
разве так можно???
ИМХО надо как-то
Код: Выделить всё
Var ResponceStream:TMemoryStream;
Begin
  ResponceStream:=TMemoryStream.Create;
  Try
      PostRequest(ResponceStream, UrlCtrl + '/api/hello', PostSource);
  Finally
      ResponceStream.Free;
  End;
End;

я не знаю, что такое PostRequest и может ли оно выбросить исключение (если это сетевой код, то не просто может, а обязательно выбросит раньше или позже) и есть ли гарантия, что PostRequest не выбросит его ДО создания потока. А то при попытке освободить несозданный объект тоже на ошибку нарвемся. Поэтому написал создание руками до Try. Если такая гарантия есть, но надо защищать так
Код: Выделить всё
Try
     ResponceStream:=PostRequest(UrlCtrl + '/api/hello', PostSource);
  Finally
Последний раз редактировалось Shleps 20.04.2022 19:27:24, всего редактировалось 1 раз.
Аватара пользователя
Shleps
постоялец
 
Сообщения: 194
Зарегистрирован: 14.06.2006 20:25:14

Re: try-finally - освобождение ресурса

Сообщение sunjob » 19.04.2022 21:15:39

меня коробит

-->
из Delphi-проекта, переношу на Lazarus
Аватара пользователя
sunjob
постоялец
 
Сообщения: 156
Зарегистрирован: 12.01.2011 15:19:54

Re: try-finally - освобождение ресурса

Сообщение Shleps » 19.04.2022 22:53:02

Я Дельфи учил по его первой версии под Windows 3.11. Тогда так и в Дельфи нельзя было.
Аватара пользователя
Shleps
постоялец
 
Сообщения: 194
Зарегистрирован: 14.06.2006 20:25:14

Re: try-finally - освобождение ресурса

Сообщение Дож » 19.04.2022 23:15:49

поясните, почему?

Ну, например, потому что так написано в документации
https://wiki.freepascal.org/Finally
https://www.freepascal.org/docs-html/ref/refse120.html

Ещё можно самостоятельно убедиться, что оно так работает
Код: Выделить всё
{$MODE OBJFPC}
uses
  SysUtils;
begin
  try
  finally
    Writeln('finally 1');
  end;
  try
    raise Exception(nil);
  finally
    Writeln('finally 2');
  end;
end.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: try-finally - освобождение ресурса

Сообщение sunjob » 20.04.2022 00:46:34

...ага, а еще я в неё ем (c)

Код: Выделить всё
{$MODE OBJFPC}
uses
  SysUtils;
begin
  raise Exception(nil);
  Writeln('exception 1');

  try
  finally
    Writeln('finally 1');
  end;

  try
    raise Exception(nil);
  finally
    Writeln('finally 2');
  end;
end.
Аватара пользователя
sunjob
постоялец
 
Сообщения: 156
Зарегистрирован: 12.01.2011 15:19:54

Re: try-finally - освобождение ресурса

Сообщение Дож » 20.04.2022 01:14:00

Да, я неправильно понял вопрос.

Если PostRequest кинет исключение, то Free действительно не будет вызван. try-finally в изначальном коде выглядит семантически лишним. Что имеет в виду автор кода нужно уточнять у него.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: try-finally - освобождение ресурса

Сообщение sunjob » 20.04.2022 04:44:47

Если PostRequest кинет исключение, то Free действительно не будет вызван

об этом и речь! точнее мысли между строк... (там еще есть где покопаться :о)
Аватара пользователя
sunjob
постоялец
 
Сообщения: 156
Зарегистрирован: 12.01.2011 15:19:54

Re: try-finally - освобождение ресурса

Сообщение Alex2013 » 20.04.2022 12:58:46

Хм ...
У меня сделано так (Возможно это какой-то другой PostRequest но вдруг пригодится)...
(использовать Goto "не кошерно" и вообще кривовато но работает )
Код: Выделить всё
// Мини парсер строк
Function Next1(Var SS:String;Ch:Char):String;
var i:Longint;
begin
Result:='';
  I:=Pos(Ch,SS);
  If i>0 then begin
   Result:= Copy (ss,1,i-1);
delete(SS,1,i);
  end
end;

//Post запрос (Разумеется  страница по URL уже проверена  )
Function PostRequestFromURL(URL,Request,SearchStr:String;
                        RP:Integer;Var HTM:String):String;
var
httpclient: TFPHTTPClient;
i: integer;
s: string;
PostData,L:TStringList;
ms:TMemoryStream;
Label L1;

begin
I:=0;
If RP=-1 then RP:= StrToInt(FProgSetting.CountRequest); //Число попыток

L1:
httpclient := TFPHttpClient.Create(nil);
  SetProxy(httpclient,fSetup.ProxyEd.Text);
httpclient.AddHeader('User-Agent',
   'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0');
try
PostData:= TStringList.Create;
PostData.Clear;
// Сборка и переформатирование запроса
Request:=Format(Request,[SearchStr]);
PostData.Clear;
Repeat
S:=Next1(Request,'|');
PostData.Add(S);
until Request='';

htm := httpclient.FormPost(URL,PostData);
     Result:=httpclient.ResponseStatusText;

   except
     Result:=httpclient.ResponseStatusText;
   end;

  if  Result<>'OK' then Begin
  Inc(I);Sleep(20); httpclient.free;
  If I<RP then Goto l1;
  end else  httpclient.Free  ;
  PostData.Free;
end;
Alex2013
долгожитель
 
Сообщения: 3039
Зарегистрирован: 03.04.2013 11:59:44

Re: try-finally - освобождение ресурса

Сообщение Vadim » 21.04.2022 07:02:33

Shleps писал(а):И от такого объявления меня коробит.
var ResponceStream := PostRequest(UrlCtrl + '/api/hello', PostSource);
разве так можно???

Неизвестно, какую версию Дельфи имел в виду автор вопроса ( :-) ), но наверное в новых версЯх так можно. По крайней мере в PascalABC.NET - это нормальное явление из-за того, что оно сделано на платформе .NET.

Добавлено спустя 13 минут 41 секунду:
sunjob
Секция "finally" ... "end" выполняется в любом случае, вне зависимости от того, произошла ошибка или нет. НО!!!!! Ошибка должна произойти (или не произойти) в коде, который стоит между "try" и "finally" (см. пример, который Вам привёл маэстро Дож). Поэтому в коде, который привели Вы и где потенциально ошибочный "PostRequest" находится до секции "try"..."finally", будет происходить стандартное аварийное завершение программы, поскольку в этом случае за обработку ошибок отвечает уже обработчик по умолчанию, а до кода, где задана обработка программистом ("try"..."finally") программа просто-напросто ещё не добралась и, поэтому, не знает, что такое возможно в принципе... ;-)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: try-finally - освобождение ресурса

Сообщение zub » 21.04.2022 10:05:07

sunjob
Похоже у изначального автора планировалось чтото одно, а получилось другое))
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: try-finally - освобождение ресурса

Сообщение Shleps » 21.04.2022 12:07:16

Vadim писал(а):По крайней мере в PascalABC.NET - это нормальное явление из-за того, что оно сделано на платформе .NET.

Мой папа не любит виртуальных машин
Где-то со времени Java 1.
Его как-то пытались соблазнить на .NET,
Но он смотрел на .NET, как будто его нет.(с)

:D
Аватара пользователя
Shleps
постоялец
 
Сообщения: 194
Зарегистрирован: 14.06.2006 20:25:14

Re: try-finally - освобождение ресурса

Сообщение Vadim » 21.04.2022 13:37:11

Shleps писал(а):Мой папа не любит виртуальных машин

Если .NET и в мыслях нет,
Значит нам пора в буфет...

:-D
Мне, кстати говоря, Java тоже не особо нравится. Что-то там всё сложно. Вдобавок, 32-ух битная версия категорически не дружит с 64-ех битной. В .NET вроде дела попроще... :-)
.NET вряд ли можно считать виртуальной машиной. Это, скорее, прослойка в виде ряда стандартных компонентов (классов), о чём в своё время говорил Вирт. Идею Sun и M$ спёрли именно у него.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: try-finally - освобождение ресурса

Сообщение sunjob » 21.04.2022 21:30:17

Vadim писал(а):Секция "finally" ...
ну да, я об этом как бы и намекал! :о)
Аватара пользователя
sunjob
постоялец
 
Сообщения: 156
Зарегистрирован: 12.01.2011 15:19:54

Re: try-finally - освобождение ресурса

Сообщение Alex2013 » 22.04.2022 15:06:50

sunjob писал(а):
Vadim писал(а):Секция "finally" ...
ну да, я об этом как бы и намекал! :о)

А просто заменить finally на except "аллах не велит" ? :wink:
Alex2013
долгожитель
 
Сообщения: 3039
Зарегистрирован: 03.04.2013 11:59:44

След.

Вернуться в Lazarus

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

Сейчас этот форум просматривают: Yandex [Bot] и гости: 5

Рейтинг@Mail.ru