LINUX.ORG.RU

Обработка ошибок и логирование


0

1

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

Что можно посмотреть как пример правильной реализации?

★★★★★
Ответ на: комментарий от pathfinder

try_call ...

Вот что-то похожее и ищу. Это общепринятая реализация или как? Если да, можно на man ссылку?

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

>Это общепринятая реализация или как?

Думаю, что нет. Это я сам придумал, а не из книжек вычитал. Мне такой подход нравится, но другим, если они будут читать мой код, понадобятся дополнительные разъяснения. Так же не гарантируется полная универсальность такого подхода, не исключено, что где-то этот подход будет неудобным.

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

ИМХО не надо злоупотреблять исключениями. Я кидаю исключения только перед экстренным завершением программы.

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

Не всегда неверный результат есть исключение. // Ушел читать статью

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

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

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

б) их медлительность чувствуется только при количестве «многатыщ или мульенов»

вот пример

$ python -m 'timeit' -s 'd=dict(zip(range(1000), range(1000)))' $'1999 in d and d[1999]'10000000 loops, best of 3: 0.0523 usec per loop

$ python -m 'timeit' -s 'd=dict(zip(range(1000), range(1000)))' $'try: d[1999]\nexcept KeyError: pass' 1000000 loops, best of 3: 0.854 usec per loop

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

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

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

> Вот что-то похожее и ищу. Это общепринятая реализация или как? Если да, можно на man ссылку?

Это NEVER DO SO реализация. Не надо повторять такого!

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

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

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

А в плюсах для некоторых может быть полной неожиданностью прерывание выполнения функции. Ещё там нет блока finally. Исключения вынуждают в каждом месте, где есть выделение/освобождение ресурсов делать блок try/catch с освобождением ресурсов и последующим перевызовом исключения, даже если тебе реакция на исключение в данном месте не нужна.

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

поймал себя на мысли, что предрасположенность к использованию исключений ни что иное как латентная goto-филия :)

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

Вы во первых использовали макросы, что само по себе - смертный грех в C++, за который я бы расстреливал, во вторых изначально закладываете архитектуру «где-то внутри бросилось, и ** с ним, - снаружи поймают и помрут», вместо того, что-бы обрабатывать исключения по месту их получения, и соотвественно adjust-ить поведение. Для мелких утилиток - такой метод мож и прокатит, но не в большом проекте.

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

>Вы во первых использовали макросы, что само по себе - смертный грех

Вы максималист. Я не спорю, что макросы могут сильно навредить. Но не надо же всё возводить в абсолют. Как показывает практика: любая мысль возведенная в абсолют - уродлива.

во вторых изначально закладываете архитектуру «где-то внутри бросилось, и ** с ним, - снаружи поймают и помрут»

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

Для мелких утилиток - такой метод мож и прокатит, но не в большом проекте.

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

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

> Вы максималист. Я не спорю, что макросы могут сильно навредить. Но не надо же всё возводить в абсолют. Как показывает практика: любая мысль возведенная в абсолют - уродлива.

Имхо уродливо выглядит связка try_begin() / try_end(), вместо того, что-бы явно написать то, что требуется синтаксисом языка.

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

Не знаю, что вы писали, в моем случае, редко бывают исключения, после которых приложение нужно шатдаунить, — обычно есть обходные пути, как сделать то-же самое, или там по тайм-ауту, итп. Хотя если речь идет не о сервисе, а о one-shot приложении, которое либо сделало что-то, либо нет, то возможно там так и будет проще, как вы делаете.

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

Для разнообразия — попробуйте так не делать ;) Попробовать другой подход.

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

>>Это NEVER DO SO реализация. Не надо повторять такого!

ЩИТО?

А оно и не надо. Я тебе щас проще объясню.[br] Представль, что ты пишешь модуль ядра. У тебя ошыбка. Что ядро будет делать с твоим «file not found»?

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

>Имхо уродливо выглядит связка try_begin() / try_end(), вместо того, что-бы явно написать то, что требуется синтаксисом языка.

Зато один раз написал и используешь в нескольких приложениях. Не, можно каждый раз писать полный try/catch, я не спорю.

Не знаю, что вы писали, в моем случае, редко бывают исключения, после которых приложение нужно шатдаунить, — обычно есть обходные пути, как сделать то-же самое, или там по тайм-ауту, итп.

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

Хотя если речь идет не о сервисе, а о one-shot приложении, которое либо сделало что-то, либо нет, то возможно там так и будет проще, как вы делаете.

В силу определенных причин мне приходится писать именно «сервисы», а не one-shot приложения. И весь мой набор софта, в конечном счете, после отладки, должен работать автономно 24/7 на контроллере, куда никто внутрь не заглянет

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

>А оно и не надо. Я тебе щас проще объясню.[br] Представль, что ты пишешь модуль ядра. У тебя ошыбка. Что ядро будет делать с твоим «file not found»?

Ядро не занимается исправлением ошибок в софте. Этим занимается программист.

//Ваш К. О.

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

>в тех местах где нет ручной проверки возврата функции

Ты не прав. Не должно быть отсутствия проверок. Все коды ошибок должны проверятся. Но это не обязательно должно писаться каждый раз вручную.

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

>Ядро не занимается исправлением ошибок в софте. Этим занимается программист.

Ты не правильно понял.[br] Делаешь ты kmalloc какой-нибудь в module_init, а памяти нет. Твой код с try_start/try_end чего сделает?

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

>Ты не правильно понял.[br] Делаешь ты kmalloc какой-нибудь в module_init, а памяти нет. Твой код с try_start/try_end чего сделает?

Не хочу тебя расстраивать, но на С++ модули для ядра не пишут. Это как раз тот случай, когда Си использовать лучше.

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

> Не хочу тебя расстраивать, но на С++ модули для ядра не пишут

4.2

ладно, спишу на неосведомленность.

val-amart ★★★★★
()
Ответ на: комментарий от pathfinder

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

должен работать автономно 24/7 на контроллере, куда никто внутрь не заглянет


по-моему, поделил на ноль. в коде, в который заглянуть и тем более быстро поправить нельзя, все ексепшены должны быть логированы, причем не просто «упс у нас где-то ошибка», а с указанием конкретно где и какая ошибка, так как нифига не выйдет «быстро локализовать ошибку». а так, у сопровождающего персонала есть возможность справиться с проблемой самостоятельно и малой кровью, так как велика вероятность того, что проблема связана со средой, а не с кодом.

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