LINUX.ORG.RU

Проблемы исключений

 


0

1

Всем привет. У меня время от времени возникает ситуация, когда вылетает исключение и перехватывается где-то далеко от места выброса. Это доставляет проблемы при поиске места и причины возникновения ошибки(потому как контекст теряется). Как чинить такое я не спрашиваю, это довольно очевидно.

Мой вопрос в следующем: как избежать подобного в принципе или хотя бы уменьшить вероятность появления таких проблем. Может быть есть какие-то техники, помогающие в этом?

вот это вопрос ). Сколько абсента выпил прежде чем его задать? Втыкай проверки на эксепшены везде где можно и будет тебе щастье

anonymous
()

Контекст теряться не должен, в той же java создавая новое исключение в конструкторе очень желательно передать исходное исключение, таким образом стектрейс будет содержать всю цепочку вызовов начиная от источника.
Еще полезно сообщение для исключения конкатенировать с предыдущем сообщением, чтоб по логам можно было приблизительно понять причинно-следственную связь, пример сообщения:
ValidationError: Invalid zip code. Сaused by: ZipCodeFormatException: faild to parse zip number. Сaused by: NumberFormatException.

Aber ★★★★★
()
Последнее исправление: Aber (всего исправлений: 1)

Звучит как нормальный сценарий работы. В чём проблема-то?

izzholtik ★★★
()
Ответ на: комментарий от Aber

Сaused by: NumberFormatException.

только как этот stacktrace помогает? Как раз ZipCodeFormatException и несет основную смысловую нагрузку, то что в родительских классах вылезло никому не интересно. Стактрейс имеет смысл именно в случае создания иерархии своих собственных классов

anonymous
()
Ответ на: комментарий от anonymous

Помогает, даже в этом искусственном случае, мы не смотря в исходники понимаем что zip код парситься из стоки в число самым простым способом, нет никаких regexp и неожиданных NPE. Значит надо искать valueOf.
Когда в проекте твоего кода меньше 5%, и во многие части проекта ты даже не заглядывал то это сильно экономит время. Мы же все таки исходим из того что сообщения в эксепшенах только для программистов и смотрят они их когда есть проблема, потому тут нет лишней инфы.

Aber ★★★★★
()
Последнее исправление: Aber (всего исправлений: 1)
Ответ на: комментарий от anonymous

Он будет в конкретный класс пальцем тыкать, а если отладочную инфу не снесли, то и в конкретную строку.

izzholtik ★★★
()
Последнее исправление: izzholtik (всего исправлений: 1)

как избежать подобного в принципе

-fno-exceptions

хотя бы уменьшить вероятность появления таких проблем

runMaybeT, runExceptT

anonymous
()
Ответ на: комментарий от Aber

Да, чейнить нужно. Но речь о другом.

Сaused by: NumberFormatException

Какой именно Number дал ошибку? Их там много. Вот эта проблема.

media_absent
() автор топика

Ты бы хоть язык указал. В питоне, например, у исключения можно посмотреть стек трейс.

Aswed ★★★★★
()
Ответ на: комментарий от media_absent

Мне кажется из сообщения очевидно что zip code -> number, в java в конце будет не просто NumberFormatException (как я написал) а более осмысленное NumberFormatException: For input string: "789-21", и вот получается что мы особо не трудились над текстом ошибки, но у нас в логе оказалось даже значение того что было передано.

Короче я считаю хорошим подходом конкатенировать сообщения ошибок на подобии чейна исчключений. Это простое правило, его легко применять и объяснить команде и оно ускоряет анализ ошибки, плюс этот подход работает против всех языков и платформ (не факт что везде можно получить нормальный стектрейс).

Aber ★★★★★
()
Последнее исправление: Aber (всего исправлений: 1)

Это доставляет проблемы при поиске места и причины возникновения ошибки(потому как контекст теряется).

Есть еще одно правило – ненужно логировать ошибку и пробрасывать её дальше. Либо перехватываешь, обрабатываешь и логируешь ошибку, либо пробрасываешь дальше по стеку.

Если логировать и пробрасывать то в случае ошибки в логе будет куча WARN,ERROR и неполных стеков. Человек это быстро поймет и начнет искать ошибку с конца лога, но в случае автоматизированного анализа логов добавятся трудности, например будут приходить уведомления об ошибке с неполной информацией, или уведомлений будет так много что у части разработчиков развоется «баннерная слепота» на ошибки.

Aber ★★★★★
()

вылетает исключение и перехватывается где-то далеко от места выброса

как избежать подобного

Не использовать исключения, возвращать код ошибки.

mrnkv
()

не использовать исключения

anonymous
()

Исключения всегда считались очень хорошей практикой.

Прямо так и записала в конспектик почему нужны исключения:

  • Исключение приводит к тому, что вызывающий код распознает состояние ошибки и обрабатывает его. Необработанные исключения останавливают выполнение программы.

  • Исключение переходит к точке в стеке вызовов, которая может справиться с ошибкой. Промежуточные функции могут позволить распространить исключение. Они не должны координироваться с другими уровнями.

  • Механизм обратной записи исключений уничтожает все объекты в области действия после возникновения исключения в соответствии с четко определенными правилами.

  • Исключение позволяет четко отделить код, который определяет ошибку, и код, обрабатывающий ошибку.

Djanik
()

Может быть есть какие-то техники, помогающие в этом?

Что за язык то? Уточнять надо. И опиши для начала свою модель использования исключений - какие исключения бросаешь (стандартные, свои), что отлавливаешь, а что нет.

anonymous
()
Ответ на: комментарий от Aber

For input string: «789-21»

Такого тоже только в простых случаях достаточно. На больших данных можно опять же несколько 789-21 получить. Если ошибка на пустой строке - совсем безнадёжно получится.

Направление мысли я понял - биндить необходимый контекст руками. Да, скорее всего ничего лучше нет. Ок.

media_absent
() автор топика
Ответ на: комментарий от mrnkv

Это никак не поможет - у тебя так же будет несколько точек возврата из функции и снаружи ты никак не узнаешь, что именно произошло.

media_absent
() автор топика
Ответ на: комментарий от media_absent

приведи конкретный код и где что ловится далеко. Твой вопрос так же туманен и обобщен как и советы погромистов здесь.

anonymous
()
Ответ на: комментарий от anonymous

Я подумал, что разницы между языками здесь нет. Кроме языков, где трейс встроен в каждое исключение - там проблема не стоит. Если важно - C++.

какие исключения бросаешь (стандартные, свои), что отлавливаешь, а что нет

Бросаются и свои, и стандартные(из stol, например). Ловятся по runtime_error и my_runtime_error(местный наследник от runtime_error) сверху.

media_absent
() автор топика
Ответ на: комментарий от media_absent

Ловятся по runtime_error

я понимаю что ловить проще о общему предку всех наследников класса ошибок, но в этом то и проблема. Ты должен сам сузить отлов ошибки до конкретной exception, а не ловить все подряд и потом лазить 3 часа в непонятных для тебя сообщениях

eco_dd
()
Последнее исправление: eco_dd (всего исправлений: 1)
Ответ на: комментарий от media_absent

Просто стд либа разных языков может быть (потенциально) построена на разных принципах, может там на каждый чих исключение летит.

Ок, по цпп расскажу как я делаю - стандартные исключиния никогда не отлавливаю (в норме), их смысл всегда - какой-то ужас-ужас, получаешь корку и идешь сомотреть бектрейс с полной инфой и по стеку, и по переменным. Свои исключения только под отлов и под конкретную узкую задачу, новая задача - новый тип. Никакой неразберихи не будет.

В цпп, кстати, какой-то стектрейс в новом стандарте завезли.

stol

Пример неудачной поделки, лучше from_chars()

anonymous
()
Ответ на: комментарий от anonymous

Свои исключения только под отлов

И ни в коем случае не надо делать их наследником от стандартных

anonymous
()
Ответ на: комментарий от media_absent

снаружи ты никак не узнаешь

Да. Придется разбираться в коде.

Но здесь:

if( !f() ) return ERROR1;
if( !g() ) return ERROR2;
if( (r = h())!=H_SUCCESS )
{
	switch( r )
	{
	case H_ERROR1:
		return ERROR1;
	case H_ERROR2:
		return ERROR3;
	default:
		return ERROR4;
	}
}
return SUCCESS;
Проще найти проблему, чем здесь:
f(); g(); h();


С другой стороны, можно воспользоваться дебагером: gdb docs
Дело вкуса...

mrnkv
()
Ответ на: комментарий от anonymous

Никому они ничего не показывают, ты просто пока ещё не понял сути. Я когда-то Страуструпа читал, так он там делал свои исключения не наследниками от std, я тогда тоже не въехал и упорно делал свои наследниками. Это был говнокод.

anonymous
()

Техника очень простая - не ловить исключения которые не нужно ловить.

slovazap ★★★★★
()

Короче, если интересно кому-то. Сделал в конфиге параметр по которому ловиться на внешнем уровне перестаёт. Соответственно, нужно не падать от пары некритичных ошибок - ставим false. Какие-то ошибки и нужно разобраться - ставим true и получаем corefile.

Иначе действительно только стектрейс или в try-catch большинство вызовов оборачивать.

media_absent
() автор топика

так исключение собственно для этого и нужны, что бы раскрутить стек до места обработки исключения — иначе как управлять и исправлять ситуацию?

что бы прога работала нормально — необходимо проверять callable сущности в блоке try{} и отлавливать исключения в блоке catch{}. Естественно, что данное относится к таким сущностям только в случае, если они не noexcept — в таком случае будет в любом случае вызван terminate.

safocl ★★
()

Раст уже посоветовали?

dimgel ★★★★★
()
Ответ на: комментарий от media_absent

оборачивай, не ленись. и вот там уже принимай решение, пробрасывать дальше или нет.

deep-purple ★★★★★
()
Ответ на: комментарий от Djanik

Исключения всегда считались очень хорошей практикой.

В среде пересылателей электронных платёжных поручений, возможно, так и есть, потому как ростовщикам гораздо выгоднее прервать ошибочное прохождение платежа, остановить программу и выбросить исключение, чем выяснять куда именно в итоге ушли денежки при возникновении ошибки.

А вот в системах автоматического управления различной техникой, например, при отказе датчика кислорода, поворотников, кондиционера и прочих узлов автомобиля двигатель не глохнет и вывозит людей с перекрёстка. Программа исполняется в любом случае, лишь отбрасывая ошибочные данные с помощью кодов возврата из подпрограмм.

Если представить основную программу мамочкой, а сбойную подпрограмму - её ребеночком, то у «бумажников» при падении ребёночка в лужу мамаша останавливается и говорит своей дитячке: «Какая же ты свинья! Посмотри на себя грязного! Фу! Теперь нам обоим придётся возвращаться домой и переодеваться». У технарей ребенок, падая в лужу, черпает ртом грязь, барахтается в зловонной жиже, но руку матери не отпускает, а мамаша идёт вперёд, лишь снизив скорость хода, в итоге вытаскивая малыша из грязи и молча таща за собой до пункта назначения.

Enthusiast ★★
()
Ответ на: комментарий от Enthusiast

а мамаша идёт вперёд, лишь снизив скорость хода, в итоге вытаскивая малыша из грязи и молча таща за собой до пункта назначения

А потом все удивляются, чо дети психами растут.

Djanik
()
Ответ на: комментарий от Enthusiast

asspalm facepalm.

кто ж тебе такое понимание исключений то в голову насадил?

deep-purple ★★★★★
()
Ответ на: комментарий от Enthusiast

В среде пересылателей электронных платёжных поручений, возможно, так и есть, потому как ростовщикам гораздо выгоднее прервать ошибочное прохождение платежа, остановить программу и выбросить исключение, чем выяснять куда именно в итоге ушли денежки при возникновении ошибки.

Шизофренический бред.

Остальное даже комментировать нет смысла, аналогия – не аргумент.

Siborgium ★★★★★
()
Ответ на: комментарий от deep-purple

Нормальная мамка помоет ребенка и переоденет в чистое. Собак и то моют, а тут дети.

Djanik
()

(потому как контекст теряется). Как чинить такое я не спрашиваю, это довольно очевидно.

Может быть есть какие-то техники, помогающие в этом?

«Не ломать», естественно, не предлагать.

t184256 ★★★★★
()
Ответ на: комментарий от deep-purple

У меня время от времени возникает ситуация, когда вылетает исключение и перехватывается где-то далеко от места выброса.

Просто не понятно где это так

tyamur ★★
()

В чем проблем смотреть в стектрейс?

ya-betmen ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.