Текущий архив: 2009.05.24;
Скачать: CL | DM;
Вниз
Re-raise исключений Найти похожие ветки
← →
It's not me (2009-03-18 13:35) [0]При выполнении конструктора некоего класса может произойти исключение номер 1.
Класс пытается выполнять некие действия, которые также могут привести к исключению номер 2. Данное исключение номер 2 обрабатывается нормально и предсказуемо. Но как бы отменить создание объекта по исключению номер 1?
То есть:constructor TMy.Create;
begin
try
<работаем работаем работаем>
except on E1:Exception do
try
<Пытаемся исправить ситуацию>;
except on E2:Exception do
<не получилось...>
<как re-raise"нуть E1?>
end;
end;
end;
← →
It's not me (2009-03-18 13:39) [1]Можно, конечно, просто сгенерировать abort. Но это как последний вариант.
Хотелось бы, чтобы код, создающий данный класс, имел информацию о том исключении, которое привело к невозможности создания класса.
← →
Palladin © (2009-03-18 13:39) [2]Raise;
← →
Palladin © (2009-03-18 13:41) [3]хотя вру... конструкция дикая...
зачем пытаться исправлять ситуацию в блоке except ?
← →
Empleado © (2009-03-18 13:43) [4]raise E1.Create?
← →
test © (2009-03-18 13:51) [5]Что то никаких идей кроме
FreeAndNil(Self)
но помойму это бред.
← →
Плохиш © (2009-03-18 14:01) [6]raise E1;
← →
It's not me (2009-03-18 14:15) [7]
> хотя вру... конструкция дикая...
предложи лучше
> зачем пытаться исправлять ситуацию в блоке except ?
хороший вопрос. А зачем вообще пытаться исправлять ошибки? имхо, затем, чтобы обойти возникшую проблему для продолжения нормального выполнения работы.
Это называется отказоустойчивость.
> Что то никаких идей кроме
> FreeAndNil(Self)
> но помойму это бред.
это действительно бред. Ты уже который раз пытаешься отвечать на вопрос при том, что тебе не хватает знаний даже понять этот вопрос.
Поизучай поведение дельфи, когда в конструкторе возникает необработанное исключение.
> raise E1.Create?
ты меня спрашиваешь? Я не знаю... )))
> raise E1;
так можно делать, это нормально?
Спасибо!
← →
Palladin © (2009-03-18 14:21) [8]constructor TMy.Create;
var
e1e:Exception;
begin
try
<работаем работаем работаем>
e1e:=Nil;
except on E1:Exception do e1e:=e1;
end;
If e1e<>Nil Then
try
<Пытаемся исправить ситуацию>;
e1e:=Nil;
except
end;
If e1e<>Nil Then Raise e1e;
end;
← →
Сергей М. © (2009-03-18 14:36) [9]
> It"s not me (18.03.09 13:35)
Как-то так:var
exptobj: Exception;
..
try
<работаем работаем работаем>
except on E1:Exception do
begin
exptobj := Exception(AcquireExceptionObject);
try
<Пытаемся исправить ситуацию>;
ReleaseExceptionObject;
except on E2:Exception do
<не получилось...>
raise excptobj;
end;
end;
end;
← →
test © (2009-03-18 14:43) [10]It"s not me (18.03.09 14:15) [7]
Извени великий учитель не признал, ты просто оставь пустые try except и все сам же обьяснял.
← →
It's not me (2009-03-18 14:55) [11]Palladin, абсолютно не понял, чем конструкция лучше. Ты просто ввел лишнюю переменную, удлинил код и убрал вложенность кода. А смысл?
Было:constructor TMy.Create;
begin
try
<работаем работаем работаем>
except on E1:Exception do
try
<Пытаемся исправить ситуацию>;
except Raise E1;
end;
end;
end;
стало:constructor TMy.Create;
var
e1e:Exception;
begin
try
<работаем работаем работаем>
e1e:=Nil;
except on E1:Exception do e1e:=e1;
end;
If e1e<>Nil Then
try
<Пытаемся исправить ситуацию>;
e1e:=Nil;
except
end;
If e1e<>Nil Then Raise e1e;
end;
ты считаешь твой код читабельнее? Хз, чем оперировать постоянно с e1e, мне читабельнее кажется мой код.
← →
Palladin © (2009-03-18 15:00) [12]
> It"s not me (18.03.09 14:55) [11]
Я тебе ничего не навязываю. Дело лично твое.
← →
It's not me (2009-03-18 15:00) [13]
> Как-то так:
ммм... А чем плох код:constructor TMy.Create;
begin
try
<работаем работаем работаем>
except on E1:Exception do
try
<Пытаемся исправить ситуацию>;
except Raise E1;
end;
end;
end;
?
← →
It's not me (2009-03-18 15:02) [14]
> Я тебе ничего не навязываю. Дело лично твое.
дык и я тебе ничего не навязываю. Ты предложил альтернативный стиль написания одного и того же по функциональности кода. Я высказал мнение, что мой вариант мне кажется более компактным и более читабельным. Вот и все )
← →
Сергей М. © (2009-03-18 15:02) [15]
> мне читабельнее кажется мой код
Если уж на то пошло, то в твоем варианте тоже требухи ненужной хватает - E1 и E2 совершенно лишние:var
exptobj: Exception;
..
try
<работаем работаем работаем>
except on Exception do
begin
exptobj := AcquireExceptionObject;
try
<Пытаемся исправить ситуацию>;
ReleaseExceptionObject;
except on Exception do
<не получилось...>
raise excptobj;
end;
end;
end;
← →
test © (2009-03-18 15:03) [16]Сергей М. © (18.03.09 15:02) [15]
Что скажешь?
type
TMy=class
private
constructor Create;
end;
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
function GetMy():TMy;
var
Form1: TForm1;
implementation
uses ConvUtils;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
x:TMy;
begin
x := GetMy;
try
if x = nil then
Memo1.Lines.add("nil");
except
on e:Exception do
Memo1.Lines.add(e.Message);
end;
end;
{ TMy }
constructor TMy.Create;
begin
inherited Create;
end;
function GetMy: TMy;
begin
try
Result := TMy.Create;
RaiseConversionError("Âñå ïëîõî");
except
Result := nil;
end;
end;
end.
← →
Сергей М. © (2009-03-18 15:15) [17]
> test © (18.03.09 15:03) [16]
Скажу - лажа.
Мемлик гарантирован.
← →
It's not me (2009-03-18 15:35) [18]
> Если уж на то пошло, то в твоем варианте тоже требухи ненужной
> хватает - E1 и E2 совершенно лишние:
в моем варианте [13] требухи в виде E2 просто нету.
E1 есть, но с тем же успехом я могу сказать, что у тебя лишнее объявление:var
exptobj: Exception;
В твоем варианте явное объявление exptobj. А в моем варианте неявное объявление E1. Монописуально, ты так не считаешь? )))
test, перестань смешить людей. Ну ты реально написал бред в видеFreeAndNil(Self)
в конструкторе. Понятно, что тем самым ты хотел освободить занятую экземпляром класса к тому времени память.
Но ты, видимо, не знаешь, что при возникновении необработанного исключения в конструкторе - дельфи автоматически очищает выделенную к тому времени память и создание объекта отменяется. Поэтому вместо FreeAndNil(Self) можно просто написать Abort; и его не обработать.
Но это в вопросе даже не спрашивалось, этот факт просто подразумевался. Вопрос был совершенно о другом, а не как остановить создание объекта.
Вместо того, чтобы признать свои пробелы в знаниях, ты решил продолжить финтить ушами. Почитай лучше литературу, всяко полезнее.
← →
Сергей М. © (2009-03-18 16:15) [19]
> в моем варианте [13]
Зато в [0] есть.
А то что ты в [13] "доточил" свой же код в [0], то в чем тогда был смысл топикстарта ?
← →
Сергей М. © (2009-03-18 16:20) [20]
> При выполнении конструктора некоего класса
А фиолетово в конструкоре это происходит или не в конструкторе.
Ежу понятно что исключение, выброшенное в конструкторе (неважно какое и какого уровня вложенности обработки), приведет к несозданию объекта.
Ты для кого, спрашивается, делал это никому не нужное уточнение, г-н агрессивный ?)
← →
test © (2009-03-18 16:27) [21]It"s not me (18.03.09 15:35) [18]
С тобой никто не говорит ты все точки над и расставил, форум/ветка не твоя собственность так что, я тебя игнорю ты меня идилия.
Сергей М. © (18.03.09 16:15) [19]
Буду думать.))
← →
Сергей М. © (2009-03-18 16:35) [22]
> test © (18.03.09 16:27) [21]
> Буду думать
А что тут думать ?
Тут пилить надо)
function GetMy: TMy;
begin
try
Result := TMy.Create; //<-- предположим, тут объект успешно создан (ресурсы под него выделены)
RaiseConversionError("Âñå ïëîõî"); //<-- хрясь исключение !
except
Result := nil; <-- попадаем сюда, нилим результат и преспокойненько возвращаем управление вызывающему коду
end;
end;
// а вот собссно и он
procedure TForm1.Button1Click(Sender: TObject);
var
x:TMy;
begin
x := GetMy; //<-- получили нил
try
if x = nil then //бесполезная проверка, ибо GetMy у тебя всегда вернет нил
Memo1.Lines.add("nil"); //вряд ли это вызовет исключение
except
// сюда никогда не попадем
on e:Exception do
Memo1.Lines.add(e.Message);
end;
end;
← →
It's not me (2009-03-18 17:02) [23]
> Ты для кого, спрашивается, делал это никому не нужное уточнение
для Test"а, который как ты не заметил в посте номер [5] предложил в конструкторе писать FreeAndNil(Self).
А за выдачу сугубо личного мнения о "ненужности" уточнения за общественное - зачот. Характеризует )
← →
Сергей М. © (2009-03-18 17:15) [24]
> для Test"а
Test (С) в топикстарте никаким боком еще не фигурировал, а упоминание конструктора было тобой сделано уже там, так что не гони уже пургу)
> о "ненужности" уточнения
А оно действительно ненужное)
По сути ты затянул бодягу про совсем другое - как по вложенном перехватчике исключения возбудить исключение, перехваченное уровнем выше.
← →
Игорь Шевченко © (2009-03-18 17:31) [25]Питер, а ты вообще нафига сюда ходишь ? У тебя проблемы с общением, или еще с чем ?
Просто интересно...
← →
Anatoly Podgoretsky © (2009-03-18 19:44) [26]> It"s not me (18.03.2009 14:15:07) [7]
> А зачем вообще пытаться исправлять ошибки?
Правильно незачем, вот я и не исправляю.
← →
vuk © (2009-03-18 20:59) [27]Непонятная тема. Исклиючния в конструкторе обрабатывать нафиг не надо. Деструктор нужно писать так, чтобы он отрабатывал нормально даже тогда, когда конструктор осыпался по исключению. Вот и весь сказ. Собственно, это в справке написано всё.
← →
Сергей М. © (2009-03-18 21:14) [28]
> vuk © (18.03.09 20:59) [27]
Конструктор тут вообще ни причем, это он его всуе приплёл для "пущей важности проблемы".
Та же самая "проблема" с теми же самыми решениями точно так же применима и к обычной регулярной процедуре или ф-ции и к любому другому методу объекта.
← →
vuk © (2009-03-18 21:24) [29]А не надо всуе приплетать, т.к. ситуации разные получаются. :)
← →
Сергей М. © (2009-03-18 21:44) [30]
> vuk © (18.03.09 21:24) [29]
Ну вот загорелось ему рерайзить E1 в момент обработки E2 !
Ну и пусть себе рерайзит, благо проблема высосана из пальца.
> как бы отменить создание объекта по исключению номер 1?
Да хоть по номер столохматому !
Цитирую самого себя:
> Ежу понятно что исключение, выброшенное в конструкторе (неважно
> какое и какого уровня вложенности обработки), приведет к
> несозданию объекта
Но автор явно не ёж, потому как шибко беспокоится, что объект останется неразрушенным, если какое-то там исключение (по барабану какое) в конструкторе не будет там же и погашено.
← →
It's not me (2009-03-18 23:09) [31]
> Исклиючния в конструкторе обрабатывать нафиг не надо. Деструктор
> нужно писать так, чтобы он отрабатывал нормально даже тогда,
> когда конструктор осыпался по исключению. Вот и весь сказ.
> Собственно, это в справке написано всё
не догнал...
Если конструктор осыпался по исключению, то создающий экземпляр класса внешний код просто не получит ссылку на этот собственно экземпляр класса. Соответственно, никак и деструктор не сможет вызвать (разве что над nil, а это уже разруливает free)... Поясни плиз.
← →
It's not me (2009-03-18 23:13) [32]
> потому как шибко беспокоится, что объект останется неразрушенным
опять ты, г-н Гений, решаешь за меня о чем я беспокоюсь.
Ежу понятно, что любое исключение в конструкторе приведет к несозданию объекта. Беспокоюсь я не об этом, а о том, какие исключение выплюнется во внешний код при несоздании объекта. И в моем случае гораздо лучше выплевывать исключение по E1, которое реально и привело к невозможности создать объект, чем исключение E2, которое лишь побочка от попыток разрулить исключение E1 и может только запутать внешний код, если он обрабатывает исключения.
← →
It's not me (2009-03-18 23:16) [33]
> Если конструктор осыпался по исключению, то создающий экземпляр
> класса внешний код просто не получит ссылку на этот собственно
> экземпляр класса
ну имеется в виду, конечно, классическое создание объекта через TClassType.Create, а не махинации со всякими InitInstance.
← →
Плохиш © (2009-03-18 23:22) [34]
> It"s not me (18.03.09 23:09) [31]
>
>
> Если конструктор осыпался по исключению, то создающий экземпляр
> класса внешний код просто не получит ссылку на этот собственно
> экземпляр класса. Соответственно, никак и деструктор не
> сможет вызвать (разве что над nil, а это уже разруливает
> free)... Поясни плиз.
>
Ты бы почитал для начала чего...
← →
Германн © (2009-03-19 00:07) [35]
> благо проблема высосана из пальца.
>
+1
← →
Palladin © (2009-03-19 00:13) [36]
> It"s not me (18.03.09 23:09) [31]
если в конструкторе класса возникает исключение, то автоматически вызывается деструктор конструируемого объекта
и кстати для этих случаев придуман free
← →
Palladin © (2009-03-19 00:19) [37]а по поводу ловли исключения именно на этапе создания (не в самом конструкторе, а именно выше уровнем) я знаю только один класс где иногда нужно это делать - TFileStream
← →
vuk © (2009-03-19 00:35) [38]to It"s not me (18.03.09 23:09) [31]:
>Поясни плиз.
Что пояснять-то? При обломе в конструкторе деструктор вызывается автоматически. Проверяется элементарно. Отладчик в помощь. И справку читать про конструкторы и деструкторы.
← →
Сергей М. © (2009-03-19 08:31) [39]
> Беспокоюсь я не об этом, а о том, какие исключение выплюнется
> во внешний код
Какое выплюнешь, такое и выплюнется.
Но это твое
> как бы отменить создание объекта
не имеет к выплевыванию какого-то конкретно интересующего тебя исключения ни малейшего отношения.
← →
Rouse_ © (2009-03-19 09:58) [40]А я бы переписал всю конструкцию...
ну или уволил бы разработчика, умудрившегося написать код, который два раза подряд может влететь в исключение...
← →
It's not me (2009-03-19 11:54) [41]Удалено модератором
Примечание: Не в пивной.
← →
It's not me (2009-03-19 12:10) [42]
> А я бы переписал всю конструкцию...
> ну или уволил бы разработчика, умудрившегося написать код,
> который два раза подряд может влететь в исключение...
Саш, извини, но ты глупость сейчас сказал.
Что значит два раза подряд влететь в исключение? Исключение лишь один из способов считай возврата ошибочного результата работы. Поэтому нужно всего лишь вызвать два раза подряд функции / методы, которые ошибку возвращают методами исключений. И тут от тебя ничего не зависит. Возвращают код ошибки - значит используешь обработку кода ошибок. Возвращают исключения - придется обрабатывать исключения.
← →
Сергей М. © (2009-03-19 12:25) [43]
> хочу выплюнуть во внешний код исключение E1, а не E2 с самого
> начала топика
Ну и хоти себе на здоровье, хоть E1 хоть E2, тем более что ничто не мешает ни хотению ни воплощению хотения)
Но конструктор-то и создание объекта причем тут ?
Можно подумать, что воплощение твоего хотения обязано чем-то отличаться, будь оно не в конструирующем, а в любом другом методе или рег.процедуре/функции)
Типа ты знаешь как это сделать НЕ в конструкторе, но вот как тоже самое сделать В конструкторе - это для тебя проблема)
Чтобы ты перестал упираться рогом, проиллюстрирую твой же вопрос в иной редакции, в которой не фигурируют ни конструктор ни какие-бы то ни было объекты, но которая отражает туже суть безо всякой "шелухи":
Kак возбудить перехваченное исключение E1 ?
Фрагмент кода иллюстрирующего проблему:try
<работаем работаем работаем>
except on E1:EException1 do
try
<Пытаемся исправить ситуацию, вызвавшую исключение E1>;
except on E2:EException2 do
<не получилось...>
<как re-raise"нуть E1?>
end;
end;
← →
It's not me (2009-03-19 12:51) [44]
> Но конструктор-то и создание объекта причем тут ?
а-а-а... Вот к чему ты решил придраться... Да, ты прав, конструктор здесь абсолютно не при чем. В привер я привел конструктор только потому, что лично у меня эта ситуация возникла именно в конструкторе. Прости пожалуйста, что я не полностью абсолютизировал вопрос.
← →
oxffff © (2009-03-19 13:02) [45]
> It"s not me (19.03.09 12:51) [44]
Я честно прочитал формулировку вопроса и у меня нет четкого представления в чем заключается вопрос.
То ли нужно по необработанному вложенному исключению генерировать внешнее, то ли еще что-то?
← →
Сергей М. © (2009-03-19 13:14) [46]Ну и кто из нас после этого "читатель" ?)
Поехали дальше.
У тебя в [0] и E1 и E2 одного и того же класса.
И в то же время в [1]
> информацию о том исключении, которое привело
Так не фиолетово ли какое исключение рерайзить - E1 или E2, если их класс одинаков ?
А если это твой грубый недочет в иллюстрации вопроса, то какого лешего в [7] ты наехал на Test (C), если сам несешь несуразицу ?
Мало того, в [31] неожиданно всплывают серьезные пробелы в элементарных знаниях ..
← →
It's not me (2009-03-19 14:31) [47]
> Так не фиолетово ли какое исключение рерайзить - E1 или
> E2, если их класс одинаков ?
кто тебе сказал, что их класс одинаков?! Указатели используются типа Exception, да, для универсальности, чтобы re-reise"ить любые исключения. Но по факту исключения то могут быть и разного класса совершенно.
Ты ведь понимаешь, что:on E:Exception do
raise E; { <-- НЕСМОТРЯ на указатель типа Exception генерируется исключение все равно того типа, которым было исключение, приведшее к обработке?! }
Кстати, по факту выяснилось, что Плохиш обманул. Так писать как он написал в [6] нельзя. В результате все это приводит к AV по крайней мере при дефолтной обработке.
Я в общем, и подозревал, чтоraise E1
слишком уж просто как-то, поэтому и завел ветку )))
Не приводит к сбоям так, как написал Сергей в [9], за что ему спасибо.
← →
It's not me (2009-03-19 14:37) [48]то есть, правильно писать с ручным использованием AcquireExceptionObject и ReleaseExceptionObject.
Как написал Palladin в [8] (то есть, перегенерирование исключения вне блока обработки исключения) - тоже неверно и приводит к AV.
Все, теперь я ответ установил. Верным в этой ветке был ответ лишь Сергея М. в [9].
← →
It's not me (2009-03-19 14:43) [49]То есть, еще раз подводя итог:
on E:Exception do
raise E;
это далеко не тоже самое, что:on E:Exception do
raise;
Я сам точно не понимаю, надо поразбираться поподробнее будет с исключениями. Так с виду похоже, чтоraise;
это какая-то magic функция. Даже отладчик ведет себя забавно - если поставить наraise;
брекпоинт и нажать F8 - то... Отладчик "перескочит" а точнее останется на этом raise. Только при втором нажатии на F8 пойдет дальше.
← →
Rouse_ © (2009-03-19 15:41) [50]
> on E:Exception do
> raise E;
Эта конструкция приводит к банальному вызову RaiseException, а вот эта:on E:Exception do
raise;
Работает в рамках текущего SEH фрейма, просто передавая управление вышестоящему обработчику.
Страницы: 1 2 вся ветка
Текущий архив: 2009.05.24;
Скачать: CL | DM;
Память: 0.62 MB
Время: 0.014 c