LINUX.ORG.RU

try-finally - освобождение ресурса (fpc/lazarus)

 ,


1

2

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

begin
var ResponceStream := PostRequest(UrlCtrl + '/api/hello', PostSource);
try
// here void
finally
  ResponceStream.Free;
  end;
end;

задал вопрос автору:

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

получил ответ:

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

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

спасибо!

p.s. данный код из Delphi-проекта, переношу на Lazarus

★★★★

Последнее исправление: sunjob (всего исправлений: 2)
Ответ на: комментарий от fornlr

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

abcq ★★
()
Ответ на: комментарий от abcq

ну да, особенно если PostRequest() вызовет исключение, кто за ним будет чистить? т.к. исключение вывалится на верхний уровень.

sunjob ★★★★
() автор топика
Последнее исправление: sunjob (всего исправлений: 1)
Ответ на: комментарий от sunjob

Если PostRequest вызовет исключение, то
1) до присваивания переменной ResponceStream дело не дойдёт и
2) в ResponceStream.Free нет смысла, пользы и ничего, кроме вреда,
разве не так?

bormant ★★★★★
()
Последнее исправление: bormant (всего исправлений: 1)
Ответ на: комментарий от sunjob

Вы о том, что

если что-то случаться в процессе отправки запроса, то не произойдет «дефолтного» освобождения рессурса

А я о том, что не произойдёт захвата ресурса. Если и произойдёт, то «ручка» от этого ресурса не вернётся, чистить захваченный таким образом ресурс или уже некому или уже поздно.

bormant ★★★★★
()
Ответ на: комментарий от bormant

или вредно :о) я об этом и «как-бы намекал»... в начале топика (не разжевывать-же самый смак, пусть интрига останется :о)

наткнулся на «его непонимание»

sunjob ★★★★
() автор топика
Ответ на: комментарий от sunjob

Ну тут возможен вариант, когда PostRequest наверх исключений не отдаёт и всегда возвращает экземпляр класса. Тут .Free нужен всегда, но этот try finally на это никак не влияет.

bormant ★★★★★
()
Ответ на: комментарий от sunjob

Обычно логика

 
try
  {хватаем} 
  try
    {работаем раз} 
    ... 
    {работаем n} 
  finally
    {освобождаем}
  end;
except
  {ошибка захвата, обработаем}
end;

Если пока «работаем» возникнет исключение, освобождение ресурса будет выполнено.

bormant ★★★★★
()
Ответ на: комментарий от bormant

если на этапе хватаем - происходит исключение, то отработает только except, а finally идет по боку, разве не так?

вот у меня выкус болтается под рукой (другой вариант)

try
except
  // If there was an error the reason can be found here
  on E: EInOutError do
  ShowMessage('File handling error occurred. Details: ' +  E.ClassName +  '/' +  E.Message);
finally
  CloseFile(tfOut);
end;

sunjob ★★★★
() автор топика
Последнее исправление: sunjob (всего исправлений: 1)
Ответ на: комментарий от sunjob

Да, по боку.
1) захват - открываем файл.
Если возникло исключение, закрывать нечего - не открылся.
2) работаем - читаем/пишем.
Если возникло исключение, файл закрыть-то все равно нужно.

bormant ★★★★★
()
Ответ на: комментарий от bormant

не успел дополнить

вообщем-то да, освобождать нечего.

еще один момент: при «обломе» во время «захвата» возможна учтека? т.е. попытка с «захватом» рессурсов и «абломом/ошибкой/исключением»

sunjob ★★★★
() автор топика
Последнее исправление: sunjob (всего исправлений: 2)
Ответ на: комментарий от sunjob

освобождать нечего

Если про «выкус» - не факт, там захват был выше этого try except finally. except фиксирует наличие ошибки ввода/вывода при работе с ресурсом, finally освобождвет захваченный ресурс.

Утечка возможна в вызванном коде, если он там что-то занял и не освободил, но такой код нельзя назвать правильным ;) В любом случае, в точке вызова об этом думать поздно:
1) либо вокникло исключение и не было обработано - управление не вернётся в оператор присваивания и ниже,
2) либо было обработано, там и должна была произойти очистка,
3) либо ниже была регистрация захваченных ресурсов, а их очистка выполняется где-то выше назначенным им владельцем.

bormant ★★★★★
()
Ответ на: комментарий от bormant

Если про «выкус»

нет, это я ваши мысли обусссоливаю :о)

вот видите, сколько подводных камней! и глубины той не видно... :о)

спасибо

sunjob ★★★★
() автор топика
Последнее исправление: sunjob (всего исправлений: 1)

Какой ужасно форматированный (да вобщем-то и вообще ужасный) код автора кода и какой орфографически ужасный вопрос от автора темы.

Не надо такое никуда переносить (лучше написать с нуля нужный функционал, а этот код смотреть в лучшем случае как референс, если там есть о чём смотреть), и не надо дурацкие вопросы задавать.

Если что, по-нормальному это можно было переформатировать так:

begin
  PostRequest(UrlCtrl + '/api/hello', PostSource).Free;
end;
но выглядит всё равно по-дурацки как сама конструкция, так и выделение отдельной функции под одну строчку. О том, что произойдёт при выбрасывании исключения внутри PostRequest, можно только догадываться (ибо его исходника тут не видно). О том, может ли PostRequest вернуть какой-нить нулевой указатель - тоже.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 5)
var
  ResponseStrem  : TResponseStream;
begin

  try
    ResponceStream := PostRequest(UrlCtrl + '/api/hello', PostSource);
  finally
    if Assigned(ResponseStream)  
      then FreeAndNil(ResponseStream);
  end;

end;

man-from-36
()
Последнее исправление: man-from-36 (всего исправлений: 1)
Ответ на: комментарий от sunjob

может там внутри самой реализации что-то есть на этот счет, никто же глубже этого куска не смотрел. Покажите как реализован PostRequest тогда можно будет уже что-то сказать, а так гадание на кофейной гуще. Но то, что у вас вызывает недоумение это похоже именно на попытку defer сделать.

abcq ★★
()
Последнее исправление: abcq (всего исправлений: 1)
Ответ на: комментарий от man-from-36

Проверка Assigned не имеет смысла - FreeAndNil сам делает такую проверку.

Переменная ResponseStream после FreeAndNil не используется - FreeAndNil избыточен и может быть заменен на простой Free.

При возникновении исключения в PostRequest значение переменной ResponseStream присвоено не будет и в ней останется случайный мусор из стека, условие Assigned сработает и FreeAndNil будет освобождать память по случайному указателю.

No ★★
()

Большое спасибо за помощь!

sunjob ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.