Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2006.09.17;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.039 c
2-1157006229
Интересующийся
2006-08-31 10:37
2006.09.17
Выбор значения в поле TDBGrid


15-1156626983
Button1
2006-08-27 01:16
2006.09.17
Подскажите кнопку, которая бы фиксировалась в нажатом состоянии?


2-1156676413
KidMan
2006-08-27 15:00
2006.09.17
Как сделать, чтобы в определенное время появлялось новое окно


2-1156749150
vain
2006-08-28 11:12
2006.09.17
Ini


2-1157027140
Sesh
2006-08-31 16:25
2006.09.17
Преобразование в char





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский