Первый тип "неуловимых" исключений мы поймать не можем. Почему? И если все-таки можем, то как?
Второй тип исключений ловится нормально, т.е. мы должны заранее "подготовить почву" под исключение, но мы не можем просто ловить исключения в блоке программы.
Больше всего меня беспокоит 5 пример: такой код в Маке и Винде вообще не вызовет исключения, программа может писать куда угодно что угодно в пределах своей "кучи". Исключение возникнет только в Линукс.
Теперь вопрос: Как правильно организовать обработку исключений для кроссплатформенного приложения?
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
H>Первый тип "неуловимых" исключений мы поймать не можем. Почему? И если все-таки можем, то как? H>Второй тип исключений ловится нормально, т.е. мы должны заранее "подготовить почву" под исключение, но мы не можем просто ловить исключения в блоке программы. H>Больше всего меня беспокоит 5 пример: такой код в Маке и Винде вообще не вызовет исключения, программа может писать куда угодно что угодно в пределах своей "кучи". Исключение возникнет только в Линукс. H>Теперь вопрос: Как правильно организовать обработку исключений для кроссплатформенного приложения?
Стандартные С++ исключения — это языковый механизм, предоставляемый программисту.
С++ "ловит" только те исключения, которые явно генерированы оператором throw.
Аппаратные аварийные прерывания возникают "самостоятельно". Некоторые из них (например, деление на ноль) программист
может "предвосхитить", явно проверяя делитель и прописав в программе оператор throw.
Но в большинстве случаев обработка аппаратных исключений — платформенно-зависимо.
Поэтому надо выделить обработку исключений в некую отдельную подсистему. Которую и переписывать для каждой системы.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
H>Первый тип "неуловимых" исключений мы поймать не можем. Почему? И если все-таки можем, то как?
Можем. Обращение по нулевому адресу под Win сгенерирует SEH исключение, которое ловится __catch (вроде) — это расширение MSVC, Но вроде и catch(...) его поймает.
H>Второй тип исключений ловится нормально, т.е. мы должны заранее "подготовить почву" под исключение, но мы не можем просто ловить исключения в блоке программы.
Не факт. p может указывать куда угодно, хотя, по идее, он должен быть инициализирован нулем, и следовательно goto 1.
3е — на перечисленных платформах сгенерируется аппаратное исключение, но в общем случае тоже не факт.
4ое — не факт. Оператор [] должен быть быстрым, и, особенно в релизе, может не проверять индекс. Для гарантированной проверки надо использовать at().
H>Больше всего меня беспокоит 5 пример: такой код в Маке и Винде вообще не вызовет исключения, программа может писать куда угодно что угодно в пределах своей "кучи". Исключение возникнет только в Линукс.
Странно, почему в линуксе возникает исключение. Компилятор (gcc?) делает проверку индекса при простом обращении к памяти? Нафик такой компилятор, это же тормозить должно. Или там в конце каждого блока некий длинный гуард блок?
H>Теперь вопрос: Как правильно организовать обработку исключений для кроссплатформенного приложения?
Как обычно. То, что вы перечислили, это просто грубые ошибки, которых не следует допускать. Их может отловить система (а не C++), но не факт.
Здравствуйте, Handler, Вы писали:
H>5) char* с = new char[2]; c[22]='a';
H>Больше всего меня беспокоит 5 пример: такой код в Маке и Винде вообще не вызовет исключения, программа может писать куда угодно что угодно в пределах своей "кучи". Исключение возникнет только в Линукс.
А какой дистрибутив Linux и какой компилятор использовались, и с какими флагами компиляции?
Здравствуйте, Handler, Вы писали:
H>>>5) char* с = new char[2]; c[22]='a';
W>>А какой дистрибутив Linux и какой компилятор использовались, и с какими флагами компиляции?
H>Я работаю на Маке gcc 4.2.1 и делаю тестовую работу. Мой проверяющий сказал, что на Линукс — это приведет к ошибке
Поставьте ему двойку и скажите, что зачет он не сдаст. Пусть побегает за вами для пересдачи, а не сдаст — пусть берет академку и возвращается через год. Приведенный код будет работать думаю на всех архитектурах без каких-либо run-time исключений (exceptions), но результат его работы не определен.
Здравствуйте, Handler, Вы писали:
H>Здравствуйте! H>Нужна Ваша консультация по исключениям.
H>try {
H>// uncatched
H>1) std::cout << *(int*)(0);
H>2) int* p; *(p)=10;
H>3) int i=10/0;
H>4) vector<int> v; v[10]=10;
H>5) char* с = new char[2]; c[22]='a';
Здесь нет ни одного оператора, который бы был должен по стандарту выбрасывать исключение. 1) разыменование нулевого указателя, 2) разыменование неинициализированного указателя, 3) деление на нуль, 4) обращение к элементу вектора за пределами его размера, 5) обращение к элементу массива за пределами его размера — это всё неопределённое поведение. Неопределённое поведение может принимать гораздо более интересные и причудливые формы, чем выброс исключения.
H>// catched
H>6) vector<int> v; v.at(10)=10;
H>}
Здесь поведение определено. vector<T>::at() при попытке обращения к невалидному индексу выбрасывает std::out_of_range.
А кроме того, прошедшее время от глагола catch — caught.
За урок англицкого отдельное спасибо (пардон, catch — неправильный глагол?).
Из обсуждения я вынес следующие вещи:
Существуют 3 типа исключений:
1. Аппаратные(деление на ноль) — не ловятся ничем
2. Стандартные (разыменование ноля) — ловятся через опции компилятора.
3. програмные (vector.at()) — ловятся стандартными методами исключений
То есть не существует единой програмной ловушки, заворачивающей все исключения?
Whoa...I did a 'zcat /vmlinuz > /dev/audio' and I think I heard God...
Здравствуйте, Handler, Вы писали:
H>За урок англицкого отдельное спасибо (пардон, catch — неправильный глагол?). H>Из обсуждения я вынес следующие вещи: H>Существуют 3 типа исключений: H>1. Аппаратные(деление на ноль) — не ловятся ничем H>2. Стандартные (разыменование ноля) — ловятся через опции компилятора. H>3. програмные (vector.at()) — ловятся стандартными методами исключений
Ерунда какая.
Что за стандартные исключения?
Исключения могут быть только программные и аппаратные, зависит от того, генерируются они апаратурой или софтом. Ловятся они всегда софтом, будь то прикладной софт или ОС. Если не ловятся, то это , как правило, остановка или крах системы.
То, что вы классифицировали как стандартное исключение — это аппаратное или системное исключение (генерирует ОС/железо). И оно не поймается через опции компилятора.
В контексте C++ можно рассматривать исключения системные и языковые. Системные — это разыменование нуля, деление на ноль, запись в "левую" память. В общем случае платформа может и не генерировать их, и тогда вы о них и не узнаете.
Языковые — это исключения, которые генерируются средствами языка, и ими же перехватываются. Язык, в общем случае, может и не иметь механизма исключений. Для C++ он есть — throw/try/catch.
H>То есть не существует единой програмной ловушки, заворачивающей все исключения?
Нет. Для ловли системных исключений есть __try/__catch (MSVC/Win), или сигналы (Unix/POSIX).
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, Handler, Вы писали:
H>>За урок англицкого отдельное спасибо (пардон, catch — неправильный глагол?). H>>Из обсуждения я вынес следующие вещи: H>>Существуют 3 типа исключений: H>>1. Аппаратные(деление на ноль) — не ловятся ничем H>>2. Стандартные (разыменование ноля) — ловятся через опции компилятора. H>>3. програмные (vector.at()) — ловятся стандартными методами исключений
M>Ерунда какая. M>Что за стандартные исключения? M>Исключения могут быть только программные и аппаратные, зависит от того, генерируются они апаратурой или софтом. Ловятся они всегда софтом, будь то прикладной софт или ОС. Если не ловятся, то это , как правило, остановка или крах системы. M>То, что вы классифицировали как стандартное исключение — это аппаратное или системное исключение (генерирует ОС/железо). И оно не поймается через опции компилятора. M>В контексте C++ можно рассматривать исключения системные и языковые. Системные — это разыменование нуля, деление на ноль, запись в "левую" память. В общем случае платформа может и не генерировать их, и тогда вы о них и не узнаете. M>Языковые — это исключения, которые генерируются средствами языка, и ими же перехватываются. Язык, в общем случае, может и не иметь механизма исключений. Для C++ он есть — throw/try/catch.
Вы хотели сказать "прерывания". Так как описываете именно прерывания. А исключения — это языковое понятие, а не платформенное или аппаратное.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Вы хотели сказать "прерывания". Так как описываете именно прерывания. А исключения — это языковое понятие, а не платформенное или аппаратное.
Ну, это зависит от терминологии. В архитектуре Intel это вроде все же называется исключениями. Но даже если вы правы, то винда генерирует системное исключение по этим прерываниям.
Здравствуйте, LaptevVV, Вы писали:
LVV>Вы хотели сказать "прерывания". Так как описываете именно прерывания. А исключения — это языковое понятие, а не платформенное или аппаратное.
Ну и в догонку — в POSIX это действительно выглядит и работает как прерывания — дергаются обработчики сигналов.
Здравствуйте, LaptevVV, Вы писали:
LVV>Вы хотели сказать "прерывания". Так как описываете именно прерывания. А исключения — это языковое понятие, а не платформенное или аппаратное.
Ай, это терминологические споры.
Прерывания — это один из аппаратных механизмов, с помощью которого можно обрабатывать исключительные ситуации.
Кстати, иногда прерываниями называют только сигналы, приходящие извне процессора (в том числе, от внешнего менеджера памяти, как в моторолах 68000, емнип), а исключениями — только то, что порождает сам процессор (его подсистема управления памятью, привилегиями, а также исполнение соответствующих инструкций).
А иногда валят в кучу и аппаратные, и программные прерывания — поскольку реакция процессора на них одинаковая: переключение контекста и вызов функции-обработчика.
Опять же, с позиций конечного пользователя, не всякое срабатывание защиты памяти является исключением. Например, это обращение к странице, которая зарезервирована, но не размещена (новая либо вытесненная в своп).
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, LaptevVV, Вы писали:
К>Ай, это терминологические споры.
Вообщем да, вы как обычно все разложили по полочкам
ЗЫ С возвращением. Без вас тут (в разделе C++) грустновато было
Здравствуйте, Marty, Вы писали:
H>>То есть не существует единой програмной ловушки, заворачивающей все исключения? M>Нет. Для ловли системных исключений есть __try/__catch (MSVC/Win), или сигналы (Unix/POSIX).
Я не знаю, как на других платформах, но для SEH можно установить \EHa флаг(в студии находится в C/C++ -> Code Generation).
В этом случае все будет ловится в try/catch блоках.
try
{
int d = 0;
int a = 1 / d;
}
catch (...)
{
cout << "exception" << endl;
}