powered by simpleCommunicator - 2.0.36     © 2025 Programmizd 02
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Правка Exception.Message при обработке исключения
25 сообщений из 26, страница 1 из 2
Правка Exception.Message при обработке исключения
    #40119535
Dimitry Timokhov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Коллеги, здравствуйте!

Иногда бывает задача при обработке исключения, дописать в его Message детализирующую информацию и сделать reraise.
Много лет пользуюсь таким механизмом:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
try
   ...
except
   on E:Exception do
   begin
      E.Message := E.Message+#13'(добавка)';
      raise;
   end;
end; 


Был уверен, что механизм надежный.

Но сегодня обнаружил, что такой механизм по-разному работает для разных классов исключений.

См. пример:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
procedure TForm1.Button1Click(Sender: TObject);
begin
   // Будет требуемое сообщение:
   //    Message 1 (O:\_temp\1\Unit1.pas, line 35)
   //    (добавка)
   try
      Assert(False, 'Message 1');
   except
      on E:Exception do
      begin
         E.Message := E.Message+#13'(добавка)';
         raise;
      end;
   end;
end;

type
   EMyExeption = class(Exception);

procedure TForm1.Button2Click(Sender: TObject);
begin
   // Будет требуемое сообщение:
   //    EMyExeption
   //    (добавка)
   try
      raise EMyExeption.Create('EMyExeption');
   except
      on E:Exception do
      begin
         E.Message := E.Message+#13'(добавка)';
         raise;
      end;
   end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
   // Будет сообщение:
   //    Access violation at address 004566C4 in module 'Project1.exe'. Read of address 00000000.
   // Я рассчитывал на сообщение:
   //    Access violation at address 004566C4 in module 'Project1.exe'. Read of address 00000000.
   //    (добавка)
   try
      TObject(nil).Destroy(); // специально вызываю EAccessViolation
   except
      on E:Exception do
      begin
         E.Message := E.Message+#13'(добавка)';
         raise;
      end;
   end;
end;

procedure TForm1.Button4Click(Sender: TObject);
var
   E: Exception;
begin
   // Дописал предыдущий пример через AcquireExceptionObject. 
   // Теперь всё ОК.
   //
   // Будет требуемое сообщение:
   //    Access violation at address 00456730 in module 'Project1.exe'. Read of address 00000000
   //    (добавка)
   try
      TObject(nil).Destroy(); // специально вызываю EAccessViolation
   except
      on Exception do
      begin
         E := AcquireExceptionObject();
         E.Message := E.Message+#13'(добавка)';
         raise E at ExceptAddr;
      end;
   end;
end;



ВОПРОС .
Что такого особенного в EAccessViolation, что он работает иначе, чем другие классы исключений?
Почему изменение EAccessViolation.Message, как указано выше в TForm1.Button3Click, игнорируется, тогда как в аналогичной ситуации изменение EMyExeption.Message учитывается?
Если реально есть что-то особенное в EAccessViolation, то где это описано?

Спасибо!

------
Delphi2007
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119537
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Timokhov, :).

а если вместо raise; написать:
Код: pascal
1.
      raise ExceptClass(e.ClassType).Create(e.Message);


?
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119538
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Timokhov
Был уверен, что механизм надежный.

Зря. Это очевидный хак, который имеет все шансы даже там, где работает - перестать в любой момент.

Dimitry Timokhov
Что такого особенного в EAccessViolation, что он работает иначе, чем другие классы исключений?

Долго объяснять словами, проще заглянуть в исходники и увидеть. Если коротко, то EAccessViolation - обёртка для виндового исключения, и в его случае объект EAccessViolation пересоздаётся во время raise.

Dimitry Timokhov
Если реально есть что-то особенное в EAccessViolation, то где это описано?

Надо просто пользоваться корректными механизмами. В данном случае это

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
procedure X(AParam: string);
try
  ...
except
  on E: Exception do
    raise AddExceptionFooter(E, 'Параметр: %s', [AParam]);
end;

function AddExceptionFooter;
begin
  { содержимое примерное, просто показывает суть, так вряд ли откомпилируется }
  raise E.ClassType.CreateFmt(E + #13 + Footer, Params);
end;
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119539
Dimitry Timokhov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ъъъъъ,

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

Удивительно само поведение - чем таким EAccessViolation отличается от моего класса исключения EMyException?
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119540
Dimitry Timokhov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
softwarer
Долго объяснять словами, проще заглянуть в исходники и увидеть. Если коротко, то EAccessViolation - обёртка для виндового исключения, и в его случае объект EAccessViolation пересоздаётся во время raise.


Вот хотелось бы это увидеть)))

Навскидку не нашел.
Правда, не так сильно искал, т.к. быстро вспомнил про AcquireExceptionObject и переписал через него.
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119541
ъъъъъ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...интересно. :)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
var
  e: Exception;
begin
  try
    TObject(nil).Destroy(); 
  except
    E := AcquireExceptionObject;
    E.Message := E.Message + #13'Добавка';
    raise e;
  end;
end;
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119568
энди
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А к чему все эти приключения? Автор таким образом пытается отследить какой AV у него дал ошибку? Так вроде это соверешенно по другому делается :)
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119579
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GetExceptionObject.CreateAVObject - тч он в самом деле особенный.

Добавление к Message интересное, как-то не обращал внимания, что оно доступно и на запись. Не сказал бы, что это хак, скорее вольность в интерфейсе, которую вряд ли станут убирать (хотя и могут)
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119592
Michael Longneck
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RaiseOuterException?
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119627
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119677
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут уже и без меня всё сказали:
1. EAccessViolation - обёртка вокруг аппаратного исключения. При raise; перебрасывается исходное исключение, а дельфёвая обёртка пересоздаётся в каждом блоке except.
2. raise EMyException - программное исключение, при raise; оно же и перебрасывается, обёрток нет.
3. AcquireExceptionObject - возможный обходной путь.
4. Но правильное решение - RaiseOuterException (или его аналог для старых версий RTL).
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119715
Dimitry Timokhov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GunSmoker,

Век живи - век учись.
Лет 20 пользуюсь подобным механизмом и иногда удивлялся, почему AV не содержат доп. информацию.
Теперь понятно.

====

Спасибо всем, кто проявил внимание к моему вопросу.

====
Александр, вопрос в тему, если не против.

Сильно сложно начать использовать www.eurekalog.com?
Это же ваш продукт, насколько помню.

Как раз сегодня засбоил jedi при построении лога у одного из заказчиков.
Лет 20 назад взял их разработку, но, видимо, пришло время менять.
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119719
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Timokhov
Сильно сложно начать использовать www.eurekalog.com?
Это же ваш продукт, насколько помню.

Я один из разработчиков, но это не мой продукт.

Насчёт "сложно" - мне, как разработчику, очевидно насколько это просто/понятно для пользователя - другой вопрос. У нас, мне кажется, достаточно подробные доки с кучей примеров. Если пользователь знаком с основами и принципами исключений в Delphi, то не думаю, что какие-то проблемы будут. А то бывают кадры, которые Range Check отключают и жалуются, что EurekaLog не ловит "исключение". Кому-то про except { тут ничего } end приходится разжёвывать.
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119751
Dimitry Timokhov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GunSmoker,

Спасибо.
Мне в свое время Rouse_ хвалил Еврику.
Попробую, как разгружусь чуток.
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119792
northener
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Timokhov
GunSmoker,

Сильно сложно начать использовать www.eurekalog.com?

Поверь мне Дима. Несложно ничуть.
В Эврике всё или почти всё уже сделано для простого и для продвинутого пользователя.
Это тебе говорю я, Германн с ДМ, который и не совсем программист, а просто ПШП.
Если я её освоил, то тебе-то какие проблемы?
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119795
Vizit0r
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 GunSmoker

Пользуясь случаем, почти по сабжу:
Когда возникает exception, а в try..except делается raise нового, то в EL репорт идет нижнее(первое) исключение, а вот в EL Filters обрабатывается верхнее.
Я себе час мозг ломал в попытках понять, почему так)

В итоге решил вопрос через EurekaLogEvents ExceptionNotify - делаю костыли типа
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
  if (AExceptionInfo.Info.ExceptionType = 'lpException') and Assigned(AExceptionInfo.InnerException) then
  begin
    if AExceptionInfo.InnerException.Info.ExceptionType = 'EConvertError' then
    begin
      AHandle := False;
      Exit;
    end;
    //тут остальные такие же
  end;



и так фильтрую.
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119800
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vizit0r,

в этом месте меня вставляет вывернутая наизнанку логика, порождающая постоянные NOT:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
{ Интерпретация ошибки ORA-3113 }
procedure Ora3113Notify(const ACustom: Pointer;
  AExceptionInfo: TEurekaExceptionInfo;
  var AHandle: boolean;
  var ACallNextHandler: boolean);
var
  Dummy: boolean;
begin
  AHandle := not (TObject(AExceptionInfo.ExceptionObject).InheritsFrom(EOraError) and (EOraError(AExceptionInfo.ExceptionObject).ErrorCode = 3113));
  ACallNextHandler := AHandle;
  if not AHandle then CurrentUser.ConnectionError(nil, EOraError(AExceptionInfo.ExceptionObject), Dummy);
end;
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119919
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer, Не увидел ничего сверхъестественного.
Компактно и нормально читается. Предложи вариант лучше
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119923
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Vizit0r
Когда возникает exception, а в try..except делается raise нового, то в EL репорт идет нижнее(первое) исключение, а вот в EL Filters обрабатывается верхнее.
Я себе час мозг ломал в попытках понять, почему так)

Дело в том, что в RTL есть только одно исключение - то, которое выбрасывается. Поэтому к нему-то фильтры и применяются. И не только фильтры, вообще вся работа идёт с ним. Все предыдущие исключения (которые в inner сохраняются) - это уже обвес EL. Т.е. в код была специально добавлена конструкция, которая вместо текущего исключения (как это в Delphi по дефолту происходило бы) в баг репорт запишет исходное. Иными словами, это специальный случай, который обрабатывается явно.

Возможно, стоит добавить новую галку "к чему применять" в свойства фильтра?
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119936
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_nigger
Компактно и нормально читается.

Потому что эту конкретную процедуру писал я. Когда такое пишет другой программист, оно обычно вдвое толще.

white_nigger
Предложи вариант лучше

Да запросто. Задать правильный вопрос - и уйдёт необходимость имитировать 3-позиционный переключатель с помощью двух булёвых переменных.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
{ Интерпретация ошибки ORA-3113 }
procedure Ora3113Notify(const ACustom: Pointer;
  AExceptionInfo: TEurekaExceptionInfo;
  var AExclude: boolean);
var
  Dummy: boolean;
begin
  AExclude := TObject(AExceptionInfo.ExceptionObject).InheritsFrom(EOraError) and (EOraError(AExceptionInfo.ExceptionObject).ErrorCode = 3113);
  if AExclude then CurrentUser.ConnectionError(nil, EOraError(AExceptionInfo.ExceptionObject), Dummy);
end;


вот так я предпочёл бы это написать.
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119938
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот это
softwarer
Код: pascal
1.
TObject(AExceptionInfo.ExceptionObject).InheritsFrom(EOraError)

нельзя ли заменить вот этим?
Код: pascal
1.
AExceptionInfo.ExceptionObject is EOraError
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40119942
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

раз я привожу к TObject - значит, он типа pointer. Так что так точно не получится. Почему InheritsFrom, а не is - сейчас уже точно не скажу. Возможно, что можно.
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40120054
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
Потому что эту конкретную процедуру писал я. Когда такое пишет другой программист, оно обычно вдвое толще.
Да ладно? Корона не жмёт? Хотя я бы перенёс на новую строчку оператор после then - стиль выработанный десятилетиями.
softwarer
вот так я предпочёл бы это написать.
Здесь вообще-то контракт другой, рефакторинг затрагивающий другие методы.
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40120055
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_nigger
Корона не жмёт?

Нет, она у меня масштабируемая.

white_nigger
Здесь вообще-то контракт другой

Гениально. И зачем ты вообще задавал вопрос?
...
Рейтинг: 0 / 0
Правка Exception.Message при обработке исключения
    #40120079
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
softwarer
Гениально. И зачем ты вообще задавал вопрос?
Пытался понять чем тебе реализация метода не угодила, вдруг что полезное услышу. А тебе оказывается архитектура кривовата
...
Рейтинг: 0 / 0
25 сообщений из 26, страница 1 из 2
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Правка Exception.Message при обработке исключения
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]