Как я могу перехватить все типы исключений в одном блоке catch?

StackOverflow https://stackoverflow.com/questions/55859

Вопрос

В C++ я пытаюсь перехватить все типы исключений за один раз (например, catch(Exception) в С#).Как это делается?И более того, как можно поймать исключения деления на ноль?

Это было полезно?

Решение

catch (...)
{
   // Handle exceptions not covered.
}

Важные соображения:

  • Лучший подход — перехватывать определенные типы исключений, от которых вы действительно можете восстановиться, а не все возможные исключения.
  • catch(...) также перехватит некоторые серьезные исключения системного уровня (зависит от компилятора), от которых вы не сможете надежно восстановиться.Перехват их таким образом, а затем проглатывание и продолжение может вызвать дальнейшие серьезные проблемы в вашей программе.
  • В зависимости от вашего контекста может быть приемлемо использовать catch(...), при условии, что исключение будет выброшено повторно.В этом случае вы регистрируете всю полезную информацию о локальном состоянии, а затем повторно генерируете исключение, чтобы оно могло распространиться.Однако вам следует прочитать Шаблон RAII если вы выберете этот маршрут.

Другие советы

Ты не хочу использовать catch (...) (т.е.поймать с помощью многоточия), если только у вас действительно, определенно и наиболее доказуемо, нет в этом необходимости.

Причина этого в том, что некоторые компиляторы (наиболее распространенные — Visual C++ 6) также превращают такие ошибки, как ошибки сегментации и другие действительно плохие условия, в исключения, которые вы с радостью можете обработать с помощью catch (...).Это очень плохо, потому что вы больше не увидите сбоев.

И технически, да, вы также можете уловить деление на ноль (для этого вам придется «StackOverflow»), но вам действительно следует избегать таких делений в первую очередь.

Вместо этого сделайте следующее:

  • Если вы действительно знаете, какие исключения следует ожидать, перехватывайте именно эти типы и не более того, и
  • Если вам нужно генерировать исключения самостоятельно и перехватывать все исключения, которые вы создадите, сделайте эти исключения производными от std::Exception (как предложил Адам Пирс) и перехватите их.

Если вы работаете в Windows и вам необходимо обрабатывать такие ошибки, как деление на ноль и нарушение прав доступа, вы можете использовать структурированный переводчик исключений.А затем внутри вашего переводчика вы можете создать исключение С++:

void myTranslator(unsigned code, EXCEPTION_POINTERS*)
{
    throw std::exception(<appropriate string here>);
}

_set_se_translator(myTranslator);

Обратите внимание: код сообщит вам, в чем заключалась ошибка.Также вам необходимо скомпилировать с параметром /EHa (C/C++ -> Генератор кода -> Включить исключения C/C++ = Да с исключениями SEH).

Если это не имеет смысла, ознакомьтесь с документацией для [_set_se_translator](http://msdn.microsoft.com/en-us/library/5z4bw5h5(VS.80).aspx)

Если перехват всех исключений, включая исключения ОС, действительно то, что вам нужно, вам нужно взглянуть на свой компилятор и ОС.Например, в Windows у вас, вероятно, есть ключевое слово «__try» или переключатель компилятора, позволяющий «try/catch» перехватывать исключения SEH, или и то, и другое.

Сделайте так, чтобы все ваши пользовательские классы исключений наследовались от std::Exception, тогда вы сможете просто перехватить std::Exception.Вот пример кода:

class WidgetError
    : public std::exception
{
public:
    WidgetError()
    { }

    virtual ~WidgetError() throw()
    { }

    virtual const char *what() const throw()
    {
        return "You got you a widget error!";
    }
};

В C++ стандарт не определяет исключение деления на ноль, и реализации, как правило, не выдают их.

Вы можете, конечно, использовать catch (...) { /* code here */ }, но это действительно зависит от того, что вы хотите сделать.В C++ есть детерминированные деструкторы (никакой чепухи с финализацией), поэтому, если вы хотите все убрать, правильно будет использовать RAII.

Например.вместо:

void myfunc()
{
    void* h = get_handle_that_must_be_released();
    try { random_func(h); }
    catch (...) { release_object(h); throw; }
    release_object(h);

}

Сделайте что-то вроде:

#include<boost/shared_ptr.hpp>

void my_func()
{
    boost::shared_ptr<void> h(get_handle_that_must_be_released(), release_object);
    random_func(h.get());
}

Создайте свой собственный класс с деструктором, если вы не используете boost.

Если я правильно помню (прошло много времени с тех пор, как я смотрел на C++), я думаю, что следующее должно помочь

try
{
 // some code
}
catch(...)
{
 // catch anything
}

и быстрый гугл(http://www.oreillynet.com/pub/a/network/2003/05/05/cpluspocketref.html), кажется, доказывает мою правоту.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top