Comments 19
У меня из этой заметки вывод один. Впрочем, ничего нового для себя.
надо быть проще… куча вложенных try...catch это не хорошо и сильно усложняет отладку
UFO just landed and posted this here
Не хватает тега «ruby» :)
4+E1
А почему этот кусок должен был выполниться? Внешний try никаких исключений не выбрасывает,
throw new Exception("E1")
это исключение считается отловленным, раз есть блок finally. Серьезно, я не совсем понимаю, какого поведения вы ждали
Суть блока
Код в блоке
В строке 4 выкидывается исключение
В блоке
Теперь у нас остаётся одно необработанное исключение
В самом конце на строке 17 выводится «5».
В результате же описанного бага, исключение
finally
в том, что он выполняется в любом случае, было ли выброшено исключение или нет. Исключения он не обрабатывает!Код в блоке
try
выполняется до места выброса исключения E1
, то есть, до строки 4 в примере. Выводится «1».В строке 4 выкидывается исключение
E1
и далее оно ловится в блоке catch
, если таковой присутствует. В данном случае блока catch
нет, поэтому исключение пробрасывается выше. Однако, есть блок finally
, который выполняется в любом случае.В блоке
finally
содержится свой блок с try...catch
, он и начинает выполняться. Внутри блока try
на строке 7 выводится «2», затем на строке 8 бросается исключение E2
(это уже второе по счёту исключение, предыдущее выброшенное исключение ещё никто не обработал!), которое тут же ловится соответствующим блоком catch
на строке 9, в котором выводится «3» (на строке 10). До строчки с выводом «4-» (строка 13) управление не дойдёт никогда.Теперь у нас остаётся одно необработанное исключение
E1
, выброшенное на строке 4. Поскольку вся эта конструкция с блоком try...finally
завёрнута ещё в один блок try...catch
, ловящий исключения нужного типа, исключение должно быть поймано на строке 14 и обработано на строке 15. В результате вывод дополнится «4+E1».В самом конце на строке 17 выводится «5».
В результате же описанного бага, исключение
E1
просто забывается, соответственно, внешний блок try...catch
его не ловит.Исключения он не обрабатывает!
Я ж не говорю, что она их именно обрабатывает. Исключение считается обработанным.
Считайте, что
try{
...
} finally {
..
}
это просто сокращенная запись
try{
...
} catch(Exception$e) {
//do nothing
} finally {
..
}
В данном случае блока catch нет, поэтому исключение пробрасывается выше
Когда блока catch нет, то выскакивает ошибка. Что наводит на мысль, что неявно он там есть.
Эм. Почему он там есть? Если нет блока
catch
, то исключение не перехватывается, не обрабатывается и, разумеется, будет ошибка (не перехваченного исключения). Или вы о какой-то другой ошибке? И почему вы решили, что?try{ ... } finally { .. }
это просто сокращенная запись
try{ ... } catch(Exception$e) { //do nothing } finally { .. }
С finally в случае исключения условно говоря вызывается вирутальная процедура, тело которой записано в блоке finally, а после этого исключение, котрое как было, так и осталось, забрасывается выше. В случае с catch перед тем как вызывать виртуальную процедуру в блоке catch, исключение удаляется из цепочки. В компилируемых языках так, наверняка, здесь аналогично.
промазал
UFO just landed and posted this here
Думаю про такой код тоже самое нельзя сказать:
А если нет разницы, зачем писать больше? :) (результат выполнения тут)
Так же думаю что описание к try/catch/finally несколько устарело и не отражает действительности раз пример в самой заметке работает и никто ранее не удивился отсутствия catch.
Опять же само по себе try-finally без catch имеет под собой смысл когда вне зависимости от тог будет брошен в try исключение или нет необходимо выполнить действие, а само исключение ловится где-то по стеку выше.
try {
try {
echo "1\n";
throw new Exception("E1");
} catch (Exception $e) {
throw $e;
} finally {
try {
echo "2\n";
throw new Exception("E2");
} catch (\Exception $e) {
echo "3\n";
}
}
echo "4-\n";
} catch (\Exception $e) {
echo "4+".$e->getMessage()."\n";
}
echo "5\n";
А если нет разницы, зачем писать больше? :) (результат выполнения тут)
Так же думаю что описание к try/catch/finally несколько устарело и не отражает действительности раз пример в самой заметке работает и никто ранее не удивился отсутствия catch.
Опять же само по себе try-finally без catch имеет под собой смысл когда вне зависимости от тог будет брошен в try исключение или нет необходимо выполнить действие, а само исключение ловится где-то по стеку выше.
UFO just landed and posted this here
Проблема именно в finally. В примерах выше видно что в зависимости от версии мы получаем на выходе различный вариант. В документации лишь необходимо поправить что try должен иметь либо хотя бы один блок независимо от того finally или catch. Опять же поведение интерпретатора относительно finally согласуется с поведением finally в Java что тоже на мой взгляд хорошо. У php, конечно, свой путь, но некоторым базовым структурам лучше бы быть унифицированнее.
Проверил на JPHP, выводит 1 2 3 4+E1 5 как и в PHP 5.6
Sign up to leave a comment.
Опасный finally или ждем 5.6