![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопрос про работу эксепшенов [XP]
cyber-pilot © (2011-01-20 14:25:00)Есть следующий код:
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.
cyber-pilot (2011-01-21 14:35:00) [1]
> Ega23 © (20.01.11 16:37) [16]
> DiamondShark © (21.01.11 01:08) [17]
Понятно. Спасибо!
KSergey (2011-01-21 09:48:00) [2]> Игорь Шевченко © (20.01.11 16:31) [15]
Не могли бы вы сказать ответ? :)
Вроде с виду код как у меня.
Или предлагается попробовать и оценить эффект?
DiamondShark (2011-01-21 01:19:00) [3]
> DiamondShark © (21.01.11 01:08) [17]
Впрочем, не только аппаратные ловушки, а вообще все исключения, порождённые операционной системой.
Все эти исключения имеют базовым классом EExternal.
DiamondShark (2011-01-21 01:08:00) [4]
> Это так специально сделано или глюк Делфи?
Это специально так сделано.
Исключения, которые генерируются в ответ на аппаратные ловушки пересоздаются.
Программные исключения используют тот же экземпляр.
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;
Ega23 (2011-01-20 16:37:00) [5]
> А вот для 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.
Игорь Шевченко (2011-01-20 16:31:00) [6]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;
Anatoly Podgoretsky (2011-01-20 16:18:00) [7]> KSergey (20.01.2011 15:48:07) [7]
Нельзя, справа должен быть объект, а не текст.
Ega23 (2011-01-20 16:10:00) [8]
> и доказывает, Palladin © (20.01.11 14:34) [2] - не правда.
Доказывает. Это два разных объектаодного и того же класса.
Есть класс, а есть экземпляр класса. Класс - один, экземпляров - от нуля до Over9000
Соответственно, в [8] проверяется принадлежность E к EZeroDivide и EConverError, после чего подымаются аналогичные по классу исключения.
Третий случай - для всех остальных классов, аналог else в case.
А на втором обработчике перехватываются уже любые исключения.
Palladin (2011-01-20 16:09:00) [9]Не понял, что доказывает?
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;
удивись
cyber-pilot (2011-01-20 15:59:00) [10]
> Ega23 © (20.01.11 15:53) [8]
Да, это мне и нужно. И обычно так все и работает, и доказывает, Palladin © (20.01.11 14:34) [2] - не правда.
А вот для AccessViolation не срабатывает.
Palladin (2011-01-20 15:55:00) [11]нет
Ega23 (2011-01-20 15:55:00) [12]
> KSergey © (20.01.11 15:48) [7]
>
> А вот так можно?
А конструктор кто вызывать будет?
Ega23 (2011-01-20 15:53:00) [13]А, я понял что тебе нужно.
Вроде как в общем случае решения нет. Тебе нужно чётко знать класс исключения. Что-то типа
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;
KSergey (2011-01-20 15:48:00) [14]Вопрос у меня чайника:
А вот так можно?
try
....
except on E: Exception do
E.Message := .....
raise E;
end;
Palladin (2011-01-20 15:33:00) [15]
> Я всегда считал, что это один и тот же объект.
я не знаю какая религия это исповедует
Ega23 (2011-01-20 15:27:00) [16]
> Но при этом в обработчике более высокого уровня я не смогу
> узнать какой тип эксепшена произошел в действительности.
> То есть не получится написать on EOutOfMemory do.
Нет проблем:
try
....
except on E: Exception do
raise Exception.Create('bla-bla-bla ' +#13#10 + E.ClassName + #13#10 + E.Message);
end;
cyber-pilot (2011-01-20 15:24:00) [17]
> 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 14:35:00) [18]
> Я всегда думал, что если писать таким образом, то к сообщения
> будут склеиваться.
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;
Palladin (2011-01-20 14:34:00) [19]E уровнем ниже не есть E уровнем выше. это два разных объекта
Dennis I. Komarov (2011-01-20 14:31:00) [20]Глюков нет. Работает так как надо.
А чего там где недоприлипло, я не понял...