Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.09.17;
Скачать: CL | DM;

Вниз

Вопреки ругани форумчан   Найти похожие ветки 

 
Loginov Dmitry ©   (2006-08-27 23:39) [0]

Тайны конструкции try..finally..end

http://matrix.kladovka.net.ru/index.php?page=tryfinally


 
guav ©   (2006-08-27 23:49) [1]

IMHO:
Не стоит надеятся на существование "безопасных" конструкторов.
Деструкторы не должны выбрасывать исключений.


 
Loginov Dmitry ©   (2006-08-27 23:54) [2]

> guav ©   (27.08.06 23:49) [1]
> IMHO:
> Не стоит надеятся на существование "безопасных" конструкторов.
> Деструкторы не должны выбрасывать исключений.


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


 
Ketmar ©   (2006-08-27 23:58) [3]

приемлемо. %-) собственно, я пишу обычно именно так, как рекомендовано в самом конце.
позволю себе дополнить: если уж развалился деструктор, то тут самое время орать "караул", гадить в лог и исчезать за горизонтом. опять же -- какие-то суперкритичные ресурсы, которые надо финализировать в любом случае -- это несколько другая сказка.


 
Мефисто   (2006-08-27 23:59) [4]

Ух... Уже и статью накропал. Читаю...


 
guav ©   (2006-08-28 00:02) [5]

Abort это тоже исключение EAbort, и Assert сюда тоже не надо, а вот про Break и Continue можно было и вспомнить

"Если в блоке finally произойдет исключение, то выполнение конструкции будет прервано."

Проверим тебя:

procedure TForm1.Button1Click(Sender: TObject);
begin
   try
     raise Exception.Create("Something is wrong");
   finally
     try
       raise Exception.Create("Something""s gone really wrong");
     except
     end;
     raise Exception.Create("Something horrible happened");
   end;
end;

Какие исключения увидит пользователь ?


 
Мефисто   (2006-08-28 00:17) [6]

Ну, насчет нескольких вложений try...finally ни борланд в VCL, ни Тейксера с Пачекой  не брезгуют.


 
vuk ©   (2006-08-28 00:18) [7]


> Данная конструкция является пожалуй самой туманной конструкцией
> среди тех, что есть в Delphi.
>


Все непонятки, которые могут возникнуть по поводу try/finally разрешаются вдумчивым чтением руководства по языку.


 
default ©   (2006-08-28 00:21) [8]

guav ©   (28.08.06 00:02) [5]
у меня AV после  "raise Exception.Create("Something""s gone really wrong");"

P.S. прости, какие нафиг тайны? это как слово "Хакер" в заглавии книги Фленова, быстро ты у него научился, однако


 
isasa ©   (2006-08-28 00:24) [9]

guav ©   (28.08.06 00:02) [5]

Тут есть маленький ньюанс. :)

Все правильно, до тех пор, пока выключен Integrated debugging.
А вот при включенном, увидим все три, по очереди.


 
guav ©   (2006-08-28 00:29) [10]

> у меня AV после  "raise Exception.Create("Something""s gone
> really wrong");"

Это где ? Версия Delphi, OC ?
У себя проверил, работает как и должно.


 
guav ©   (2006-08-28 00:31) [11]

> guav ©   (28.08.06 00:02) [5]
>
> Тут есть маленький ньюанс. :)

Чтобы избежать его, я написал
> Какие исключения увидит пользователь ?


 
Ketmar ©   (2006-08-28 00:31) [12]

> [9] isasa ©   (28.08.06 00:24)
а без IDE и VCL -- два MessageBox()"а, потом "Application Error". %-)


 
isasa ©   (2006-08-28 00:39) [13]

guav ©   (28.08.06 00:31) [11]
А пишущий программу, не пользователь?

В примере нет  прерываний. Все три raise выполнятся. Первый - штатно, сообщение второго подавлено пустым except, а третий, как всегда...


 
guav ©   (2006-08-28 00:40) [14]

Из [0]
P := nil;
P1 := nil;
try
 ...
 GetMem(P, 255);
 GetMem(P1, 2000000000);
finally
 ...
 FreeMem(P);
 FreeMem(P1);
end;


FreeMem не поднимает исключение если P = nil, но это не документировано, не стоит этим пользоваться.


 
default ©   (2006-08-28 00:43) [15]

guav ©   (28.08.06 00:29) [10]
Delphi 6, Me
вот в C# пашет

try
  {
   throw new Exception();
  }
  finally
  {   //Получили исключение в try идём в finally на завершение
   Console.WriteLine("1");
   try
   {   // ой, опять исключение, и в finally к тому же, что будет?
   
    throw new InvalidOperationException();
   }
   catch
   {   // ого, мы тут! значит первое исключение в finally
    // не выводит его из строя!
    Console.WriteLine("2");
   }
   // и мы даже тут!
   Console.WriteLine("3");
  }
  // всяческие возгласы удивления добавлена для картинности,
  // а не реального удивления


 
default ©   (2006-08-28 00:44) [16]

offtopic
в какой раз уже код с кривым форматированием постится? как лечить?


 
guav ©   (2006-08-28 00:53) [17]

offtopic
> в какой раз уже код с кривым форматированием постится? как
> лечить?

Студия табывставляет заместо пробелов (отучается в Tools>Options>Text Editor вроде), а форум не хочет их делать, .


 
default ©   (2006-08-28 00:55) [18]

guav ©   (28.08.06 00:53) [17]
что-то Дмитрий притих, неужели к написанию второй статьи приступил


 
Ketmar ©   (2006-08-28 01:30) [19]

> [14] guav ©   (28.08.06 00:40)
поэтому есть ReallocMem(), который ещё и переменную скинет в nil. %-)


 
Loginov Dmitry ©   (2006-08-28 07:45) [20]

Как всегда всем чего-то не нравится.

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


 
Furyz ©   (2006-08-28 09:35) [21]

Клевая статья , спасибо


 
BiN ©   (2006-08-28 10:18) [22]


> vuk ©   (28.08.06 00:18) [7]
>
> Все непонятки, которые могут возникнуть по поводу try/finally
> разрешаются вдумчивым чтением руководства по языку.


Согласен.
Тема немного смахивает на "Секреты оператора сложения. Всё что вы хотели знать, но боялись спросить."
-)


 
Ketmar ©   (2006-08-28 10:36) [23]

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


 
guav ©   (2006-08-28 12:22) [24]

> что в статье нужно изменить, чтобы ее было не стыдно показывать
> людям?

В [5] я немного намекнул.

Польза сомнительна.
Если я что-л прочитаю в учебнике или статье я всё равно проверю по справке, а не буду путаться искать статьи. Если я вижу чьи то заблуждения, то, чтобы устранит их, я буду ссылаться на справку.
Статьи я буду уже искать если справка неясна или информация покажется не соответствующей действительности. При этом тут следует и самому всё проверять, а не только статьи читать.


 
default ©   (2006-08-28 13:05) [25]

Loginov Dmitry ©   (28.08.06 07:45) [20]
уже дано достаточно замечаний [5], [14], [19]
я бы добавил, что выносить за try строки вроде "FileStream := TFileStream.Create("MyFile.txt", fmOpenRead);" вообще говоря не стоит
если нет никаких внешних обработчиков исключения
ну, допустим пользователь указывает файл куда нужно дописать данные и неправильно набрал имя файла - что программа должна на этом остановиться? ясно, что могут быть в принципе случаи где можно и остановиться, но они редки, по крайней мере - надо об этом упомянуть
и на будущее - перед написанием статьи неплохо было бы изучить справку, по мне так - лучше бы перевод оттуда пусть и вольный кинуть чем твои самопальные пункты 1) 2)3)4)


 
default ©   (2006-08-28 13:16) [26]

не совсем точно выразился...
короче я к тому, что исключения могущие возникнуть в строках наподобие
"FileStream := TFileStream.Create("MyFile.txt", fmOpenRead);"  вообще говоря надо обрабатывать, а не плевать на них, мол ресурс не занят и хрен с ним с исключением...


 
guav ©   (2006-08-28 13:36) [27]

> default ©  

Вообще - исключения надо обрабатывать.
Но в VCL это уже сделано, причём централизованно, и в подобных слуаях мало причин вмешиваться. Результат такой обработки исключения  EFOpenFileError - вполне адекватный.
Когда тербуется дополнительная обработка исключения, стоит применить except с raise; , чтобы сохранить исключение для дальнейшей обработки.

Если файл задаётся через диалог, то следует предусмотреть опцию FileMustExist, и тогда исключение - действительно будет дейсвительно нестадартной ситуацией.

Ещё, на тему обработки исключений, если функция вызывается сторонним API, выпускать  из неё исключения не всегда безопасно, часто приходится обрабатывать их по месту возникновения.


 
default ©   (2006-08-28 13:49) [28]

guav ©   (28.08.06 13:36) [27]
не всегда исключения надо обрабатывать


 
guav ©   (2006-08-28 13:53) [29]

> [28] default ©   (28.08.06 13:49)

И это тоже.
Например исключение StackOverflowException :-)


 
default ©   (2006-08-28 13:59) [30]

guav ©   (28.08.06 13:53) [29]
ага:)
заглушать некоторые исключения и давать системе работать дальше как ни в чём не бывало это как давать стрелять бойцу с раненой рукой - может и в своего попасть


 
Loginov Dmitry ©   (2006-08-28 18:36) [31]

Исправил статейку. Выложил туда свой вариант перевода справки по try..finally. Постарался исправить так, чтоб все было без придирок.

Однако, до сих пор не могу понять, как можно было столько времени и себе и всем мозги тр..ть, когда всего-то нужно было прочитать справку. Просто полагал, что справку уже давно перевели всякие Фароновы, Архангельские, а фигушки! Наверно дословный перевод этой темы для них - слишком сложное дело. (вот Архангельския и нафигачил отсебятины).

Статья получилась суховатой, зато полезной (надеюсь :)).


 
default ©   (2006-08-28 19:07) [32]

Loginov Dmitry ©   (28.08.06 18:36) [31]
так лучше, ещё FreeMem поправь, см. [14]

"Часто бывают случаи, когда в программе должна выполниться определенная часть кода, несмотря на то, что выполняемый до нее код может быть прерван вследствие возникновения исключительной ситуации. "
в скобочках пометить(что также вследствие Exit, Break, Continue)

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

try
    try
      raise EZeroDivide.Create("");
    finally
      // теряем исключение EZeroDivide
      // для избежания этого нужно обрабатывать исключение EOverflow
      raise EOverflow.Create("");
    end;
  except
    on EZeroDivide do ShowMessage("EZeroDivide");
    on EOverflow do ShowMessage("EOverflow");
  end;

  try
    try
      raise EZeroDivide.Create("");
    finally
      try
        raise EOverflow.Create("");
      except
      end;
    end;
  except
    on EZeroDivide do ShowMessage("EZeroDivide");
    on EOverflow do ShowMessage("EOverflow");
  end;

правда тут придётся предполагать знание блоков try except end;
можно написать статью о try except end и в настоящей статье сослаться на неё, если хочешь

хотя, как уже упоминали, ценность подобных статей невелика...
посмотри у Рихтера разделы по защищённым блокам и обработки исключений
там куча примеров, вот если напишешь что-то подобное только с содержательными примерами на Delphi, то ценность такой статьи резко возрастёт


 
Loginov Dmitry ©   (2006-08-28 19:23) [33]

> так лучше, ещё FreeMem поправь,


Так уже ж подправил вроде бы.


> вот это можно примером подкрепить, с потерей и без

Это же перевод справки. Как-то некорректно будет вносить в него дополнительные изменения.


 
default ©   (2006-08-28 19:30) [34]

Loginov Dmitry ©   (28.08.06 19:23) [33]
"Как-то некорректно будет вносить в него дополнительные изменения."
это не изменение, а примеры подкрепляющие сказанное, так быстрее доходит, думаю дойдёт даже если о try except end не слыхали


 
guav ©   (2006-08-28 19:50) [35]

Вспомнил кстати, как я делал, когда объектов было действительно много.
Инициализация и финализация всех в куче требовала внимательности.
Тода я решил использовать такой вариант.

 ObjectList := TObjectList.Create;
 try
   //...
   SomeObject := TSomeClass.Create;
   try
     ObjectList.Add(SomeObject);
   except
     SomeOjbect.Free;
     raise;
   end;
   ...
   SomeObject2 := TSomeClass2.Create;
   try
     ObjectList.Add(SomeObject2);
   except
     SomeOjbect2.Free;
     raise;
   end;
 ...
 finally
   ObjectList.Free;
 end;

, но потом отказался от этого, решив что вложенные try лучше и разбив функцию на части.


 
Loginov Dmitry ©   (2006-08-28 19:54) [36]

Опять этот мифический TObjectList. Сколько их всего в Delphi?
Где-то один находил, так он оказался тем же TList, только все параметры Pointer были изменены на TObject. Название модуля уже не помню. Искал поиском с помощью файл-менеджера.


 
default ©   (2006-08-28 20:03) [37]

мда


 
guav ©   (2006-08-28 20:22) [38]

> он оказался тем же TList, только все параметры Pointer были
> изменены на TObject.

не только...

cмотри исходники... читай справку... в данном случае хватит одного из двух.


> [37] default ©   (28.08.06 20:03)

и не говори


 
Ketmar ©   (2006-08-28 21:07) [39]

> [36] Loginov Dmitry ©   (28.08.06 19:54)
ничего мифического. rtfs contnrs.pas.


 
Loginov Dmitry ©   (2006-08-29 02:52) [40]

Всего какой-то простенький, невзрачный, перекрытый метод Notify, но зато сколько функциональности!!!



Страницы: 1 2 вся ветка

Текущий архив: 2006.09.17;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.062 c
1-1154589474
Mechanic
2006-08-03 11:17
2006.09.17
TGraphicControl не принимает MouseWheel


2-1157020656
валет
2006-08-31 14:37
2006.09.17
ip адреса


15-1156336634
fishka
2006-08-23 16:37
2006.09.17
Проблемы при работе с сетью (папка с DBF открыта для доступа)


2-1156603720
The_SloN
2006-08-26 18:48
2006.09.17
Нужно добавить программу в службы


2-1157090505
Rubey
2006-09-01 10:01
2006.09.17
Справочник в виде дерева