MadExcept + пробовать / окончательно блокировать?
У меня есть некоторый код Delphi, вроде этого:
try
//some code
//occasionally throws an exception here, for example an EIndexOutOfRangeException
//more code...should get skipped if exception is thrown
finally
// there may or may not be any important cleanup code here
end;
Исключением в этом случае является не то, что требует обработки, кроме выхода из блока try. Итак, до того, как в проект был добавлен mad-exc для устранения ошибок, этот код работал. Но теперь я получаю сообщения об ошибках, потому что MadExcept сообщает о необработанном исключении.
Схожий вопрос : триггеры MadExcept при попытке наконец указывают на то, что поведение MadExcept в таких обстоятельствах является "ожидаемым", поскольку исключение не "обрабатывается".
Я хотел бы получить некоторые пояснения о том, что мои варианты - это способы предотвращения появления всплывающего диалогового окна при запуске этого кода, независимо от того, было ли выброшено и проигнорировано внутреннее исключение.
Так что я прав, думая, что нет никакого переключателя, чтобы отключить MadExcept для взлома необработанных исключений в блоке try/finally? И мне нужно явно "поймать" исключение, даже если я хочу его игнорировать?
Должен ли я делать что-то вроде этого (игнорировать любые исключения):
try
//some code
//sometimes throws EIndexOutOfRangeException here
//more code...should get skipped if exception is thrown
except do begin end;
end;
или возможно (игнорируйте очень конкретное исключение):
try
//some code
//sometimes throws EIndexOutOfRangeException here
//more code...should get skipped if exception is thrown
except on E : EIndexOutOfRangeException do begin end;
end;
или, может быть, это должно быть:
try
try
//some code
//sometimes throws EIndexOutOfRangeException here
//more code...should get skipped if exception is thrown
except on E : EIndexOutOfRangeException do begin end;
finally
// some cleanup code
end;
Если все три из них являются действительными решениями, должен ли я предпочесть одно другому другому по какой-либо причине?
2 ответа
Так что я прав, думая, что нет никакого переключателя, чтобы отключить MadExcept для взлома необработанных исключений в блоке try/finally?
Да. try/finally
не обработка исключений; это гарантированная очистка, независимо от того, происходит ли исключение. В качестве таких, try/finally
блоки совершенно не имеют отношения к инструментам обработки исключений, таким как MadExcept.
И мне нужно явно "перехватить" исключение, даже если я хочу его игнорировать?
Да. Вот как работают исключения. Они работают вниз по стеку, пока не найдут обработчик, который поймает их. Если такого обработчика не существует, ОС интерпретирует его как сбой и завершает работу программы. Делфи TApplication
object устанавливает обработчик очень близко к нижней части стека вызовов, чтобы ваша программа не зависала, и MadExcept перехватывает это так, что, если исключение достигнет этой точки, будет сгенерирован отчет.
Если вы хотите игнорировать исключение, да, вам нужно его перехватить, потому что формально вы обрабатываете исключение, перехватывая его в этой точке стека, раскручивая и игнорируя его. Эта часть о "перехвате его в этой точке в размотке стека" важна, поскольку это означает, что размотка стека останавливается в этой точке, и программа возобновляет нормальное выполнение. Если вы просто проигнорируете это (т.е. ничего не сделали с этим в своем коде, в том числе не устанавливали обработчик исключений), он продолжит разматывать стек вплоть до обработчика по умолчанию, независимо от того, установлен ли MadExcept или нет.
Так что да, в этом случае пример № 2 - правильный курс действий. Пример №3 будет также допустимым, если у вас есть код очистки, который необходимо выполнить на этом этапе. Но пример № 1 никогда не должен выполняться ни при каких обстоятельствах, потому что это может означать, что вы можете проигнорировать исключение, которого вы не ожидали, и в конечном итоге вы повредите в своей программе и никогда не узнаете об этом.
Мне кажется, что у вас есть фундаментальное неправильное понимание того, что finally
средства.
finally
Блок не влияет на распространение исключения. Это просто гарантирует, что finally
блок будет выполняться, даже если возникла исключительная ситуация, или нормальный поток выполнения был изменен exit
, break
и т.п.
Примите попытку / окончательно и madExcept все равно сообщит, что программа вызвала исключение, которое не было обработано.
Есть способы сказать madExcept игнорировать определенные исключения. Например, некоторые исключения должны молчать. Канонический пример такого EAbort
, Вы бы использовали RegisterExceptionHandler
настроить обработку необработанных исключений. Хотя, как я объясню, я сомневаюсь, что это решение вашей проблемы.
Что вам нужно сделать дальше, это забыть о madExcept. Вы должны решить, что делать с этим исключением. Вы хотите обработать это здесь, или вам нужно позволить распространению исключения? Только ты действительно можешь это знать. Но madExcept здесь не водитель. Что должно повлиять на ваше решение, так это правильное выполнение вашей программы. Должно ли обрабатываться исключение или нет, чтобы ваша программа работала правильно? Сначала вы должны понять это правильно, а потом беспокоиться о madExcept.
Если вам нужно разобраться с этим здесь, то обращайтесь с этим избирательно. Не ловите все исключения. Это абсолютное нет-нет. Но если вы справитесь с этим здесь, спросите себя, разумно ли это. Код не смог выполнить какое-либо действие. Есть ли какой-то последующий код, который полагается на то, что действие завершается успешно? Обрабатывая ошибку и игнорируя ее, как вы предлагаете, вы заставляете весь последующий код быть неоднозначным относительно успеха или неудачи этого действия. Это кажется мне очень сомнительным.
Теперь исключение EIndexOutOfRangeException
, Это означает, что вы написали что-то вроде A[i]
где значение i
является недействительным. Я не могу придумать сценарий, где это было бы приемлемо. Поэтому мне кажется, что ваша программа содержит ошибку и просто использует недопустимый индекс. Вы должны исправить эту ошибку должным образом, не выходя за пределы. Не подавляйте исключение, перестаньте его поднимать.
Еще один способ взглянуть на это. Как вы можете определить разницу между вашей текущей ситуацией и тем, что возникнет в результате написания A[-i]
вместо A[i]
? Подавление исключения означает, что вы не можете обнаружить такие вопиющие ошибки, как эта.
Суть в том, насколько я могу судить, что madExcept сообщает об ошибке в вашем коде. Вы должны рассматривать madExcept как своего друга и слушать, что он говорит. Он говорит вам, что у вас есть дефект в вашем коде, который должен быть исправлен.