| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Как перехватить исключение |
| Автор: neosapient 10.10.2014, 14:57 | ||
| Здравствуйте. Настроил проект на перехват исключений в настройках проекта: С\С++ -> Code Generation Enable C++ Exeption = Yes With SEH Exceptions (/EHa) Тестирую обычное деление на 0 - исключение перехватывается. Делаю более сложный тест: обращаюсь к -1 (минус первой) ячейке вектора
И программа падает, а исключение перехватить не получается (( P.S. Прикрепил пример с программой к посту. (test_exeption.zip) Использую Visual Studio 2008 P.P.S. Для тех кто любит веб IDE, http://ideone.com/YaVxGX Но исключений в этой веб IDE не возникает, так что для демонстраций она бесполезна |
| Автор: sQu1rr 10.10.2014, 15:03 |
| Ну так а кто сказал что исключение должно бросаться http://www.cplusplus.com/reference/vector/vector/operator%5B%5D/ бросается тут: std::vector::at() http://www.cplusplus.com/reference/vector/vector/at/ |
| Автор: neosapient 10.10.2014, 15:13 |
| Хм, а что тогда происходит? Там же (в глубинах std-библиотеки) нет exit(-1); ? Программа вылетает - надо это как то перехватить. Какие есть варианты? |
| Автор: sQu1rr 10.10.2014, 15:17 | ||
то есть arr[-1] - вполне валидно, и вы сами должны проверять плохо это или хорошо. ваша программа вылетает, потому что visual studio шаманит с памятью, наделе же это UB |
| Автор: neosapient 10.10.2014, 15:36 |
| Может есть какие-либо флаги в настройке проекта, чтобы visual studio не шаманила с памятью? Что значит аббревиатура UB? |
| Автор: DarthTon 10.10.2014, 16:05 | ||
Вы точно в релиз билде запускаете? А то в дебажном оно просто покажет assertion failed; это перехватывать не стоит. В релизном будет Access violation по адресу 0xFFFFFFFC(т.к. пустой вестор по-умолчанию инициализирует начальный указатель в 0) которое нормально ловится catch(...). UD - undefined behavior. В общем случае поведение не определено, ибо arr[-1] фактически вернёт значение в ячейке которая находится перед ячейкой 0-го елемента вектора. А состояние той ячейки может быть каким-угодно. В веб ИДЕ исключение не возникает потому что там оптимизирована строка "int val = arr[-1];" и она не исполняется на самом деле. |
| Автор: neosapient 10.10.2014, 16:32 |
| DarthTon, Ни в дебаге, ни в релизе исключение в catch не ловится |
| Автор: sQu1rr 10.10.2014, 16:37 |
С чего бы это? Потому что С++ не генерирует исключения такие вещи. вы объясните что вы хотите реализовать |
| Автор: korian 10.10.2014, 16:48 | ||
я думаю в релизе не должна вылетать. покрайней мере не на этой строчке. Потому шо это с точки зрения языка вполне нормальная законная операция, которая не подразумевает никаких ошибок. И врядли оно выделит память там, где в [-1] нельзя писать. а segfault наверно в эксепшены не оборачивается, бо нормально восстановиться после такого нереально |
| Автор: DarthTon 10.10.2014, 17:12 | ||
Ибо /Eha и Access violation. В этом случае crt функция FindHandlerForForeignException пытается найти catch(...) хендлер в списке SEH фреймов, и если находит, в этот хендлер передаётся Win32 исключение преобразованное к С++ исключению. А вообще, что происходит при выполнение программы? Она падает? Где падает, с каким исключением? |
| Автор: Lukkoye 10.10.2014, 18:26 | ||
| Вы хотите что то типа такого? http://rextester.com/LGS53967
Если вкратце, существует особый вид исключений: системные. Система догадывается о том, что ваша программа ведет себя не корректно по её поведению: например, она пытается сделать чтение там, где не должна была бы читать (выход за пределы диапазона массива). В этом случае система решает ликвидировать сбойное приложение, что бы оно не мешало нормальной работе всей системы в целом. И посылает сбойному приложению сигнал. Некоторые сигналы приложение может обработать, и после этого даже остаться в живых. После некоторых сигналов гибель приложения становится неизбежной. В этом случае система лишь уведомляет о неизбежном. В общем почитайте о сигналах. Так же рекомендую к прочтению о seh exception https://ru.wikipedia.org/wiki/%D0%A1%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%B0%D1%8F_%D0%BE%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0_%D0%B8%D1%81%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B9 |
| Автор: neosapient 10.10.2014, 19:30 | ||
| Lukkoye, спасибо за ответ. Но обработчик исключения не сработал в программе собранной VC9. Может надо флаги какие-нибудь включить? P.S.
|
| Автор: Lukkoye 10.10.2014, 19:44 | ||
Мне не очевидно, что именно вы имеете ввиду под "исключением". |
| Автор: bsa 21.10.2014, 15:43 |
| Если мне память не изменяет, то catch не ловит SEH исключения. Их ловит __catch. В любом случае, ЛОВИТЬ ДАННЫЕ ИСКЛЮЧЕНИЯ НЕЛЬЗЯ. Если возникло такое исключение, то ты должен исправить его причину в программе, а не подставлять костыли по восстановлению дальнейшей работы программы. Так как не исключено, что дальнейшая работа просто невозможно. |
| Автор: neosapient 21.10.2014, 17:40 |
| тут вопрос надо рассматривать с такой точки зрения: как найти место, где программа упала (особенно, если в программе много кода)? |
| Автор: baldina 21.10.2014, 18:03 |
открой Debug->Exceptions и включай Thrown на все подряд |
| Автор: bsa 22.10.2014, 14:14 |
| это делается под отладчиком. В крайнем случае путем загрузки кор-дампа. Неверный доступ к памяти вылавливается довольно легко. Особенно, в отладочной сборке. |