Ieroglif
19 / 19 / 2
Регистрация: 23.06.2011
Сообщений: 238
|
|
1 | |
Когда и где следует использовать механизм исключительных ситуаций?31.07.2014, 20:25. Просмотров 861. Ответов 11
Метки нет Все метки)
(
Вечер добрый, товарищи.
Вопрос у меня в общем-то теоретический и, наверное, размытый, общий. Когда и где следует использовать механизм исключительных ситуаций? Как лучше всего их обрабатывать? Когда и где этот механизм использовать НЕ стоит? Если возможно, с примерами. К Страуструпу посылать не надо – читал.
0
|
|
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
|
31.07.2014, 20:25 |
Ответы с готовыми решениями:
11
Когда и где следует использовать механизм исключительных ситуаций? Когда следует использовать функции помимо main? Обработка исключительных ситуаций Обработка исключительных ситуаций Обработка исключительных ситуаций! |
0x10
2771 / 1863 / 317
Регистрация: 24.11.2012
Сообщений: 4,618
|
|
31.07.2014, 20:36 | 2 |
Ответ будет примерно таким же, ибо вопрос обработки ошибок сам по себе не из простых.
Тут еще можно более-менее конкретно сказать. 1. В конструкторах - с осторожностью. Следить за тем, чтобы генерация исключения не вела к утечкам памяти. 2. В деструкторах никогда. 3. Плохой идеей будет строить на исключениях логику передачи управления при нормальном ходе выполнения программы (а-ля goto). Вспоминаем, что исключения - инструмент обработки ошибок. Следовательно, используем для информирования вызывающего кода о произошедших ошибках. Особенно удобно, когда вместе возникновения ошибки недостаточно информации для ее корректной обработки. Напрямую зависит от самого исключения. Где-то логично завершить работу приложения. Где-то - залогировать ошибку и продолжить работу. Но все, что сказал выше, у Страуструпа описано. Что еще добавить?
0
|
Ieroglif
19 / 19 / 2
Регистрация: 23.06.2011
Сообщений: 238
|
|
31.07.2014, 21:02 [ТС] | 4 |
Не могли бы привести реальные или приближенные к реальным примеры? Желательно, разномастные.
0
|
31.07.2014, 21:02 | |
0x10
2771 / 1863 / 317
Регистрация: 24.11.2012
Сообщений: 4,618
|
|
31.07.2014, 21:25 | 5 |
1. Попытка создать вектор отрицательного размера (в общем случае - невозможность захвата ресурса).
2. Подача на вход парсеру невалидной строки. 3. Выход за границы массива. 4. Невозможность продолжения выполнения программы из-за невыполнения одного из этапов алгоритма.
0
|
Voivoid
710 / 282 / 16
Регистрация: 31.03.2013
Сообщений: 1,339
|
|
31.07.2014, 22:51 | 6 |
По поводу этого пункта я бы уточнил. Бросать исключение стоит только в случае, если данные на вход передаются из надежного источника от которого мы не ожидаем невалидных данных. А вот в случае если мы ожидаем данные от ненадежного источника ( например пользовательский ввод ), то имеет смысл возвращать код ошибки, потому что вероятно все равно придется сразу же проверять что там удалось напарсилось, а писать конструкции вида:
try { parse(); } catch ... это не очень. Ну или по крайней мере имеет смысл делать две функции, одна бросает исключения, а другая возвращает код ошибки
0
|
Tulosba
:)
![]() 4752 / 3246 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
|
|
31.07.2014, 23:04 | 8 |
Это вроде как бустовский подход. Про всю либу не уверен, но в boost::asio активно практикуется.
Там, где можно диагностировать ошибку, но ещё неясно как её следует обработать. Типичная ситуация - разработка библиотечного кода.
0
|
IGPIGP
Комп_Оратор)
![]() |
||||||
01.08.2014, 02:16 | 9 | |||||
Ieroglif, вот довольно смешной код. Я пытался показать ситуацию, когда без генерации и обработки исключения обойтись трудновато, хотя может и заблуждаюсь.
0
|
Voivoid
710 / 282 / 16
Регистрация: 31.03.2013
Сообщений: 1,339
|
|
01.08.2014, 03:04 | 10 |
1
|
Evg
![]() ![]() |
|
02.08.2014, 13:35 | 12 |
На пальцах можно сказать, что в любом культурном компиляторе поддержка исключений устроена так, что оператор try работает очень быстро, а оператор throw/catch работает очень медленно. Ещё одной особенностью исключения является многоуровневый выход из процедур.
Поэтому все эти механизмы используются в основной своей массе для обработки ошибочных ситуаций в программе, которые возникают редко и для которых не требуется большой скорости работы. Но можно использовать и для других целей. Т.е. понятия "исключительная ситуация" и "ошибка" НЕ эквивалентны Возьмём некоторый абстрактный алгоритм, который устроен в виде цепочки вызовов. При этом может получиться, что входные данные для алгоритма заданы некорректно, но это выясняется глубоко (т.е. через несколько вызовов). А поэтому если делать реализацию без исключительных ситуаций, то получится так, что, допустим, ошибка может обнаружиться на 10-м уровне вложенности, а потому чтобы вернуть в точку начала информацию об ошибке требуется все промежуточные 9 уровней вложенности писать так, чтобы они тоже следили за этой ошибкой Типа того: C++ int main (void) { /* Вызываем наш алгоритм. Если в ответ вернули true, значит всё хорошо, * если вернули false, значит были ошибки во входных данных */ res = func (...); if (res == false) /* выдаём информацию об ошибке */ } bool func (...) { ... res = func1 (...); if (res == false) /* Где-то на нижних уровнях случилась ошибка, возвращаем * информацию об этом наверх */ return false; ... return true; } /* Здесь по смыслу всё то же самое */ bool func1 (...) { ... res = func2 (...); if (res == false) /* Где-то на нижних уровнях случилась ошибка, возвращаем * информацию об этом наверх */ return false; ... return true; } /* Далее по такому принципу ещё несколько уровней */ bool func10 (int x, int y) { ... /* И вот уже на самом низком уровне мы можем проверить, * что какие-то промежуточно вычисленные параметры оказываются * некорректными */ if ((a + b) > 10 && (a * b) < 7 && ....) return false; ... return true; } В этом случае более удобным будет механизм с исключениями, т.к. он многуровневый и тратит много времени на исполнение только в случае возникновения исключительной ситуации. Если таких ситуаций не случилось, то программа работает быстро и лишних вычислений делает по минимуму и только там, где нужно C++ int main (void) { /* Вызываем наш алгоритм. Если было брошено исключение, значит * были ошибки во входных данных */ try { func (...); } catch (...) { /* выдаём информацию об ошибке */ } } /* Обращаем внимание на то, что нам уже не нужно возвращать * информацию о корректности или неорректности */ void func (...) { ... func1 (...); ... } /* Здесь по смыслу всё то же самое */ void func1 (...) { ... func2 (...); ... } /* Далее по такому принципу ещё несколько уровней */ void func10 (int x, int y) { ... /* И вот уже на самом низком уровне мы можем проверить, * что какие-то промежуточно вычисленные параметры оказываются * некорректными. И только здесь мы генерируем исключительную * ситуацию, про которую более высокие уровни даже не знают, * а потому и не тратят время на её обработку */ if ((a + b) > 10 && (a * b) < 7 && ....) trow ...; ... }
5
|
02.08.2014, 13:35 | |
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
|
02.08.2014, 13:35 |
Обработка исключительных ситуаций. Обработка исключительных ситуаций Обработка исключительных ситуаций Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |