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

Вниз

Обработка ошибок или как работает Except   Найти похожие ветки 

 
КаПиБаРа ©   (2005-03-09 08:22) [0]

Имеется код
procedure TForm1.Button1Click(Sender: TObject);
begin
 try
   with TForm2.Create(self) do
   try
     DoSomefing;
   finally
     Free;
   end;
 except
 end;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
 raise Exception.Create("Ошибка в onCreate");
end;

procedure TForm2.DoSomefing;
begin
 raise Exception.Create("Ошибка в методе DoSomefing");
end;


Объясните почему появляется сообщение "Ошибка в onCreate", а "Ошибка в методе DoSomefing" не появляется. Почему второе сообщение не появляется я заю, но почему появляется первое? В чем отличие механизма подавления первой и второй ошибки?


 
Александр Иванов ©   (2005-03-09 08:36) [1]

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


 
КаПиБаРа ©   (2005-03-09 08:41) [2]

Александр Иванов ©   (09.03.05 8:36) [1]
Неа... доходит.


 
Digitman ©   (2005-03-09 08:43) [3]

событие TForm.OnCreate возникает в контексте конструктора формы автоматически сразу после успешного завершения конструирования всех компонентов, "брошенных" на эту форму в дизайн-тайм

поскольку в теле обработчика TForm.OnCreate возбуждается необрабатываемое исключение, объект-форма не создается (точнее - экз-р тут же разрушается), а управление передается на блок except


 
КаПиБаРа ©   (2005-03-09 08:50) [4]

Digitman ©   (09.03.05 8:43) [3]
Я или тупой или у меня объект создается, т.к. код

procedure TForm2.DoSomefing;
begin
 ShowMessage(Caption);
 raise Exception.Create("Ошибка в методе DoSomefing");
end;


выводит название формы "Да зраствует 1 мая!";


 
Digitman ©   (2005-03-09 09:00) [5]


> КаПиБаРа ©   (09.03.05 08:50) [4]


сначала


> Почему второе сообщение не появляется я заю


а теперь уже


> код
> procedure TForm2.DoSomefing;
> begin
>  ShowMessage(Caption);
>  raise Exception.Create("Ошибка в методе DoSomefing");
> end;


как это понимать ?
то "выводится" оно у тебя, то не "выводится" ...


 
sniknik ©   (2005-03-09 09:02) [6]

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TForm2.Create(self) do
  try
    DoSomefing;
  finally
    Free;
  end;
end;

и все будет


 
КаПиБаРа ©   (2005-03-09 09:14) [7]

Переделал код что бы было более понятно.
procedure TForm1.Button1Click(Sender: TObject);
begin
 try
   with TForm2.Create(self) do
   try
     DoSomefing;
   finally
     Free;
   end;
 except
   ShowMessage("Что то случилось!");
 end;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
raise Exception.Create("Ошибка в onCreate");
end;

procedure TForm2.DoSomefing;
begin
ShowMessage(Caption);
raise Exception.Create("Ошибка в методе DoSomefing");
end;


Описание тестирования:
Запускаю файл Project1.exe
На главной форме нажимаю кнопку.
Появляется окно с заголовком "Project1", краным крестиком, кнопкой ОК и сообщением "Ошибка в onCreate.".
Нажимаю на ОК.
Появляется окно с заголовком "Project1", кнопкой ОК и сообщением "Да здравствует первое мая!" (это и есть заголовок Form2).
Нажимаю на ОК.
Появляется окно с заголовком "Project1", кнопкой ОК и сообщением "Что то случилось!".
Нажимаю на ОК.
Закрываю приложение.

Выводы и вопросы:
Выходит метод DoSomefing все таки вызывается и Exception генерируемый в нем гасится моим try except, а почему все таки не гасится Except в OnCreate?


 
КаПиБаРа ©   (2005-03-09 09:26) [8]

Или так:
procedure TForm1.Button1Click(Sender: TObject);
begin
 try
   with TForm2.Create(self) do
   try
     DoSomefing;
   finally
     Free;
   end;
 except
   on E: Exception do ShowMessage("Что то случилось! " + E.Message);
 end;
end;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
raise Exception.Create("Ошибка в onCreate");
end;

procedure TForm2.DoSomefing;
begin
ShowMessage(Caption);
raise Exception.Create("Ошибка в методе DoSomefing");
end;


Описание тестирования:
Запускаю файл Project1.exe
На главной форме нажимаю кнопку.
Появляется окно с заголовком "Project1", краным крестиком, кнопкой ОК и сообщением "Ошибка в onCreate.".
Нажимаю на ОК.
Появляется окно с заголовком "Project1", кнопкой ОК и сообщением "Да здравствует первое мая!" (это и есть заголовок Form2).
Нажимаю на ОК.
Появляется окно с заголовком "Project1", кнопкой ОК и сообщением "Что то случилось! Ошибка в методе DoSomefing".
Нажимаю на ОК.
Закрываю приложение.

Выводы и вопросы:
Выходит метод DoSomefing все таки вызывается и Exception генерируемый в нем гасится моим try except, а почему все таки не гасится Except в OnCreate?


 
Digitman ©   (2005-03-09 09:36) [9]


> КаПиБаРа ©   (09.03.05 09:14) [7]


падон .. в случае с формой ее объект в дан.случае не разрешается
необработанное тобой исключение передается на обработку объекту Application, и в нем, если ты не назначил обработчик OnException, просто вызывается метод ShowException (выводящий сообщение об исключении), исключение "гасится" (raise там не вызывается)


 
КаПиБаРа ©   (2005-03-09 09:42) [10]

Digitman ©   (09.03.05 9:36) [9]
В каком месте этот код можно посмотреть, а то я что то искал, но найти не мог.


 
KSergey ©   (2005-03-09 09:46) [11]

> [7] КаПиБаРа ©   (09.03.05 09:14)
> Переделал код что бы было более понятно.
> Описание тестирования:

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

Дело в том, что пользовательский обработчик OnCreate формы в VCL покрыт try/except с полным подавлением исключения.

Таким образом, если даже в обработчике OnCreate происходит исключение - выводится сообщение - но дальше все идет своим чередом. Зачем - мне не понятно.

Для примера попробуйте перекрыть AfterConstruction, например (никто тогда ничего госить не будет) - и поведение сразу изменится (перенести туда функциональность из OnCreate)


 
КаПиБаРа ©   (2005-03-09 09:47) [12]

Digitman ©   (09.03.05 9:36) [9]
И еще вопрос. Зачем сделана эта хитрость с передачей исключения объекту Application?
Невозмжность погасить внешним try except исключение в методе onCreate введена с каким то умыслом или это побочный эффект при работе какой-то схемы обработки исключений?


 
KSergey ©   (2005-03-09 09:48) [13]

> [10] КаПиБаРа ©   (09.03.05 09:42)
> Digitman ©   (09.03.05 9:36) [9]

Что касается момента, описанного Digitman - см. реализацию Application.Run


 
Digitman ©   (2005-03-09 10:08) [14]


> КаПиБаРа ©   (09.03.05 09:47) [12]


>  каком месте этот код можно посмотреть


это - модуль Forms

см. реализацию метода TCustomForm.DoCreate, в теле которого кака раз и вызывается метод Application.HandleException


> Зачем сделана эта хитрость с передачей исключения объекту
> Application?


видимо, Борланд дает тем самым тебе возможность централизованной обработки искл.ситуаций, потенциально возникающих при конструировании форм

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

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


 
КаПиБаРа ©   (2005-03-09 10:41) [15]

Digitman ©
KSergey ©

Спасибо.

constructor TCustomForm.Create(AOwner: TComponent);
begin
 GlobalNameSpace.BeginWrite;
 try
   CreateNew(AOwner);
   if (ClassType <> TForm) and not (csDesigning in ComponentState) then
   begin
     Include(FFormState, fsCreating);
     try
       if not InitInheritedComponent(Self, TForm) then
         raise EResNotFound.CreateFmt(SResNotFound, [ClassName]);
     finally
       Exclude(FFormState, fsCreating);
     end;
     if OldCreateOrder then DoCreate;
   end;
 finally
   GlobalNameSpace.EndWrite;
 end;
end;

procedure TCustomForm.DoCreate;
begin
 if Assigned(FOnCreate) then
 try
   FOnCreate(Self);
 except
   if not HandleCreateException then
     raise;
 end;
 if fsVisible in FFormState then Visible := True;
end;

function TCustomForm.HandleCreateException: Boolean;
begin
 Application.HandleException(Self);
 Result := True;
end;


Еще вопрос:

Зачем HandleCreateException оформлен в виде функции, если он возвращает всегда True?


 
Digitman ©   (2005-03-09 10:49) [16]


> Зачем HandleCreateException оформлен в виде функции, если
> он возвращает всегда True?


этот protected-метод - динамический.
ты вправе перекрыть его в любом своем наследнике и тем самым реализовать нужную тебе логику

например, если перекрыть этот метод вот так

function TForm2.HandleCreateException: Boolean;
begin
Result := False;
end;

то все твои вопросы сразу отпадут


 
КаПиБаРа ©   (2005-03-09 10:55) [17]

Digitman ©   (09.03.05 10:49) [16]
Спасибо.



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

Форум: "Основная";
Текущий архив: 2005.03.20;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.05 c
14-1109537438
nick-from
2005-02-27 23:50
2005.03.20
CMS


14-1109495138
cyborg
2005-02-27 12:05
2005.03.20
Скорость работы Линукса


1-1109763659
hgd
2005-03-02 14:40
2005.03.20
Кто знает о компоненте TIEEE1394-beta


1-1109860385
SAI
2005-03-03 17:33
2005.03.20
Memo


1-1110177575
Alexandre
2005-03-07 09:39
2005.03.20
Как запустить другое приложение?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский