Как стать автором
Обновить

Комментарии 19

У меня из этой заметки вывод один. Впрочем, ничего нового для себя.
О, спасибо, что поделились выводом! :)
Сам вывод озвучивать нельзя: сольют карму.
надо быть проще… куча вложенных try...catch это не хорошо и сильно усложняет отладку
Они могут быть вложены и внешне неявно. Одна функция вызывает другую внутри блока try, та — другую и т. д.
НЛО прилетело и опубликовало эту надпись здесь
Не хватает тега «ruby» :)
4+E1

А почему этот кусок должен был выполниться? Внешний try никаких исключений не выбрасывает,
throw new Exception("E1") это исключение считается отловленным, раз есть блок finally.
Серьезно, я не совсем понимаю, какого поведения вы ждали
Суть блока 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, исключение удаляется из цепочки. В компилируемых языках так, наверняка, здесь аналогично.
НЛО прилетело и опубликовало эту надпись здесь
Думаю про такой код тоже самое нельзя сказать:

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 исключение или нет необходимо выполнить действие, а само исключение ловится где-то по стеку выше.
НЛО прилетело и опубликовало эту надпись здесь
Проблема именно в finally. В примерах выше видно что в зависимости от версии мы получаем на выходе различный вариант. В документации лишь необходимо поправить что try должен иметь либо хотя бы один блок независимо от того finally или catch. Опять же поведение интерпретатора относительно finally согласуется с поведением finally в Java что тоже на мой взгляд хорошо. У php, конечно, свой путь, но некоторым базовым структурам лучше бы быть унифицированнее.
НЛО прилетело и опубликовало эту надпись здесь
Проверил на JPHP, выводит 1 2 3 4+E1 5 как и в PHP 5.6
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации