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

Вниз

Вопрос про работу эксепшенов   Найти похожие ветки 

 
cyber-pilot   (2011-01-20 14:25) [0]

Есть следующий код:

procedure TForm1.Button1Click(Sender: TObject);
var
 vSL: TStringList;
begin
 try
   try
     vSL.CommaText := "";
   except
     on E: Exception do
     begin
       E.Message := "Msg1: " + E.Message;
       raise;
     end;
   end;
 except
   on E: Exception do
   begin
     E.Message := "Msg2: " + E.Message;
     ShowMessage(E.Message);
     raise;
   end;
 end;
end;


Я всегда думал, что если писать таким образом, то к сообщения будут склеиваться. В этом же случае происходит Access Violation и информация о добавленных строчка почему-то теряется. Это так специально сделано или глюк Делфи?
Проверял в Delphi 2007 и Delphi XE.


 
Dennis I. Komarov ©   (2011-01-20 14:31) [1]

Глюков нет. Работает так как надо.

А чего там где недоприлипло, я не понял...


 
Palladin ©   (2011-01-20 14:34) [2]

E уровнем ниже не есть E уровнем выше. это два разных объекта


 
Ega23 ©   (2011-01-20 14:35) [3]


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


1. Чтобы "склеивалось" делается так:
try
 ....
except on E: Exception do
 raise Exception.Create("bla-bla-bla  " + E.Message);
end;


2. AV получаешь закономерно, ибо обращаешься к свойству несозданного объекта vSL.CommaText := "";
Надо так:
vSL := TStringList.Create;
try
 try
   vSL.CommaText := "";
   .....
 except on E: Exception do
   raise Exception.Create("bla-bla-bla  " + E.Message);
 end;
finally
 vSL.Free;
end;


 
cyber-pilot   (2011-01-20 15:24) [4]


> Palladin ©   (20.01.11 14:34) [2]
>
> E уровнем ниже не есть E уровнем выше. это два разных объекта

Я всегда считал, что это один и тот же объект.


> 1. Чтобы "склеивалось" делается так:
> try
>  ....
> except on E: Exception do
>  raise Exception.Create("bla-bla-bla  " + E.Message);
> end;

Но при этом в обработчике более высокого уровня я не смогу узнать какой тип эксепшена произошел в действительности. То есть не получится написать on EOutOfMemory do.


> 2. AV получаешь закономерно, ибо обращаешься к свойству
> несозданного объекта vSL.CommaText := "";

Это я специально написал, чтобы ошибку вызвать.


 
Ega23 ©   (2011-01-20 15:27) [5]


> Но при этом в обработчике более высокого уровня я не смогу
> узнать какой тип эксепшена произошел в действительности.
>  То есть не получится написать on EOutOfMemory do.


Нет проблем:

try
....
except on E: Exception do
raise Exception.Create("bla-bla-bla  " +#13#10 + E.ClassName + #13#10 +  E.Message);
end;


 
Palladin ©   (2011-01-20 15:33) [6]


> Я всегда считал, что это один и тот же объект.

я не знаю какая религия это исповедует


 
KSergey ©   (2011-01-20 15:48) [7]

Вопрос у меня чайника:
А вот так можно?

try
....
except on E: Exception do
   E.Message := .....
   raise E;
end;


 
Ega23 ©   (2011-01-20 15:53) [8]

А, я понял что тебе нужно.
Вроде как в общем случае решения нет. Тебе нужно чётко знать класс исключения. Что-то типа


procedure TForm4.Button1Click(Sender: TObject);
begin
 try
   try
     ShowMessage(FloatToStr(5/StrtoInt(Edit1.Text)))
   except
    on E: EConvertError do raise EConvertError.Create("Первый обработчик" + #13#10 + E.Message);
     on E: EZeroDivide do raise EZeroDivide.Create("Первый обработчик" + #13#10 + E.Message);
     on E: Exception do raise Exception.Create("Первый обработчик (а фиг знает)" + #13#10 + E.Message);
   end;
 except on E: Exception do
   ShowMessage("Второй обработчик" + #13#10 + E.Message);
 end;
end;


 
Ega23 ©   (2011-01-20 15:55) [9]


> KSergey ©   (20.01.11 15:48) [7]
>
> А вот так можно?


А конструктор кто вызывать будет?


 
Palladin ©   (2011-01-20 15:55) [10]

нет


 
cyber-pilot   (2011-01-20 15:59) [11]


> Ega23 ©   (20.01.11 15:53) [8]

Да, это мне и нужно. И обычно так все и работает, и доказывает, Palladin ©   (20.01.11 14:34) [2] - не правда.
А вот для AccessViolation не срабатывает.


 
Palladin ©   (2011-01-20 16:09) [12]

Не понял, что доказывает?

try
  try
    vSL.CommaText := "";
  except
    on E: Exception do
    begin
      E.Message := "Msg1: " + E.Message;
      ShowMessage(IntToStr(Integer(E)));
      raise;
    end;
  end;
except
  on E: Exception do
  begin
    E.Message := "Msg2: " + E.Message;
    ShowMessage(IntToStr(Integer(E)));
  end;
end;

удивись


 
Ega23 ©   (2011-01-20 16:10) [13]


>  и доказывает, Palladin ©   (20.01.11 14:34) [2] - не правда.


Доказывает. Это два разных объекта одного и того же класса.
Есть класс, а есть экземпляр класса. Класс - один, экземпляров - от нуля до Over9000
Соответственно, в [8] проверяется принадлежность E к EZeroDivide и EConverError, после чего подымаются аналогичные по классу исключения.
Третий случай - для всех остальных классов, аналог else в case.
А на втором обработчике перехватываются уже любые исключения.


 
Anatoly Podgoretsky ©   (2011-01-20 16:18) [14]

> KSergey  (20.01.2011 15:48:07)  [7]

Нельзя, справа должен быть объект, а не текст.


 
Игорь Шевченко ©   (2011-01-20 16:31) [15]

KSergey ©   (20.01.11 15:48) [7]

procedure raiseOOM;
begin
 raise EOutOfMemory.Create ("gothca");
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 try
   raiseOOM;
 except
   on E: Exception do
   begin
     E.Message := "Foo";
     raise E;
   end;
 end;
end;


 
Ega23 ©   (2011-01-20 16:37) [16]


> А вот для AccessViolation не срабатывает.


EAccessViolation is raised when an application:

Dereferences a nil (Delphi) or NULL (C++) pointer.
Writes to memory reserved for executable code.
Attempts to access a memory address for which there is no virtual memory allocated to the application.
Run-time exception information is saved in fields provided by EExternal.

Note:  Applications should not raise EAccessViolation directly, but should instead rely on the run time to raise this exception.


 
DiamondShark ©   (2011-01-21 01:08) [17]


>  Это так специально сделано или глюк Делфи?

Это специально так сделано.
Исключения, которые генерируются в ответ на аппаратные ловушки пересоздаются.
Программные исключения используют тот же экземпляр.


var
 P: ^Integer;
 a, b: double;
 i, j: integer;
begin
 P := nil;
 a := 0;
 b := 0;
 i := 0;
 j := 0;
 try
   try
// раскоментировать по вкусу
//      raise EAccessViolation.Create("koo!"); // один и тот же экземляр
//      raise Exception.Create("qwe"); // один и тот же экземляр
//      i := i div j; // разные экземпляры
//      writeln(i); // чтоб оптимизатор код не выкинул
//      a := a / b; // разные экземпляры
//      writeln(a); // чтоб оптимизатор код не выкинул
//      P^ := 1; // разные экземпляры
   except
     on E: Exception do
     begin
       E.Message := "Msg1: " + E.Message;
       ShowMessage(IntToStr(Integer(E)));
       raise;
     end;
   end;
 except
   on E: Exception do
   begin
     E.Message := "Msg2: " + E.Message;
     ShowMessage(IntToStr(Integer(E)));
   end;
 end;
end;


 
DiamondShark ©   (2011-01-21 01:19) [18]


> DiamondShark ©   (21.01.11 01:08) [17]

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


 
KSergey ©   (2011-01-21 09:48) [19]

> Игорь Шевченко ©   (20.01.11 16:31) [15]

Не могли бы вы сказать ответ? :)
Вроде с виду код как у меня.

Или предлагается попробовать и оценить эффект?


 
cyber-pilot   (2011-01-21 14:35) [20]


>  Ega23 ©   (20.01.11 16:37) [16]


> DiamondShark ©   (21.01.11 01:08) [17]

Понятно. Спасибо!



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

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

Наверх




Память: 0.52 MB
Время: 0.013 c
15-1294754988
12
2011-01-11 17:09
2011.04.24
На панели задач хочу название кнопки Delphi7 + Имя_проекта.


6-1236577141
kernel
2009-03-09 08:39
2011.04.24
Зависание IdHTTPProxyServer


15-1294834077
George
2011-01-12 15:07
2011.04.24
TIdHTTP.Get и Windows 7


2-1295032117
Сергей
2011-01-14 22:08
2011.04.24
Вызов функции из функции


6-1236780712
d@vinchi
2009-03-11 17:11
2011.04.24
Возможно ли TIdCmdTCPServer принять многострочную команду?