LINUX.ORG.RU

вопрос по исключениям в с++


0

0

В общем наткнулся на такую интересную проблемку при работе с исключениями, вот мой код:

#include <iostream>
#include <exception>
#include <stdexcept>

class Exception : public std::exception {
  public:
    Exception() throw() {}
    explicit Exception(const std::string &m) throw()
      : exception()
    { mess_ = m; }
    ~Exception() throw() {}

    const char* what() const throw() { return mess_.c_str(); }

    private:
      std::string mess_;
};

class LogicException : public std::logic_error {
  public:
    explicit LogicException(const std::string &m) throw()
      : std::logic_error(m)
    {}
    ~LogicException() throw() {}
};

class RealyBadException {};

void f() throw(Exception, std::bad_exception) {
        //throw Exception("Exception from f()"); //случай f1
        //throw LogicException("LogicException grom f()"); //случай f2
        //throw RealyBadException();  //случай f3
}

int main()
{
        try {
                f();
        } catch (std::bad_exception const& ex) {
                std::cout << "std::bad_exception" << std::endl;
        } catch (std::exception const& ex) {
                std::cout << ex.what() << std::endl;
        } catch (...) {
                std::cout << "Something realy odd" << std::endl;
        }
}

Так вот, суть проблемы вот в чем согласно книжке Б.Страуструпа по С++ если я нарушаю спецификацию исключений ф-ии ( в функции void f() throw(Exception) сгенерю исключение RealyBadException или LogicException) то вызывается ф-ия unexpected(),а затем terminate() что приводит к остановке программы. Если я добавлю к спецификации исключений std::bad_exception, то в точке вызова появится возможность перехватить исключение std::bad_exception - это в теории. Что же происходит на практике.

1) Если раскоментировать "случай f1", то все идет как и должно быть, исключение ловится во втором болке catch ф-ии main()
2) Если раскоментировать "случай f2" тогда в окне терминала я получаю следующее сообщение:

terminate called after throwing an instance of 'LogicException'
  what():  LogicException grom f()
Aborted

3) И в последнем случае f3 я получаю

terminate called after throwing an instance of 'RealyBadException'
Aborted


хотя последние 2 случая должны ловица в первом блоке catch ф-ии main(). Кто сможет растолковать почему программа аварийно завершается вместо того чтобы обработать исключение.
anonymous

Дефолтный unexpected_handler просто и без заморочек вызывает terminate
(пункт 18.6.2.2 стандарта, "The implementation's default
unexpected_handler calls terminate()."). Если тебе нужна такая
функциональность, как отлов неопознанных исключений, нужно задать свой
обработчик через set_unexpected, и в нем явно делать rethrow (в
bad_exception оно преобразуется автоматически, если кинутое
обработчиком исключение не соответствует спецификации функции,
которая все это начала).

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

Блин, реально. Устанавливаю следующую ф-ию как unexpected_handler и все пучком:

void my_handler()
{
  throw;
}

Спасибо... :)

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

Может ещё кто объяснит разницу между unexpeted() и terminate() ? Насколько я понял unexpected() вызывается только при нарушении спецификации исключений ф-ии, а terminate() если во время раскрутки стэка (из-за исключения) какой либо из деструкторов объектов сгенерит исключение. B вообще мне не очень ясен смысл terminate() разве нельзя было обойтись только unexpected() ?

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

> Может ещё кто объяснит разницу между unexpeted() и terminate() ?
> Насколько я понял unexpected() вызывается только при нарушении
> спецификации исключений ф-ии, а terminate() если во время раскрутки
> стэка (из-за исключения) какой либо из деструкторов объектов сгенерит
> исключение.

Для terminate есть еще несколько возможных вариантов, на самом деле.
Они перечислены в стандарте.

> B вообще мне не очень ясен смысл terminate() разве нельзя
> было обойтись только unexpected() ?

Собственно разница только в том, что unexpected может попробовать как-то
разрулить ситуацию (в виде rethrow), там, где это имеет смысл (и
используется именно и только в таких случаях), а terminate - нет.

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