C ++ ловит все исключения - PullRequest
212 голосов
/ 25 ноября 2008

Есть ли c ++ эквивалент Java

try {
    ...
}
catch (Throwable t) {
    ...
}

Я пытаюсь отладить код Java / jni, который вызывает собственные функции Windows, и виртуальная машина продолжает падать. Нативный код выглядит хорошо при модульном тестировании и, кажется, только сбой при вызове через jni. Общий механизм перехвата исключений оказался бы чрезвычайно полезным.

Ответы [ 14 ]

299 голосов
/ 25 ноября 2008
try{
    // ...
} catch (...) {
    // ...
}

перехватит все исключения C ++, но это следует считать плохим дизайном. Вы можете использовать новый механизм current_exception в c ++ 11, но если у вас нет возможности использовать c ++ 11 (устаревшие системы кода, требующие перезаписи), то у вас нет указателя именованного исключения, который можно использовать для получения сообщения или имени , Возможно, вы захотите добавить отдельные предложения catch для различных исключений, которые вы можете поймать, и поймать только все внизу, чтобы записать неожиданное исключение. E.g.:

try{
    // ...
} catch (const std::exception& ex) {
    // ...
} catch (const std::string& ex) {
    // ...
} catch (...) {
    // ...
}
127 голосов
/ 25 ноября 2008

Кто-то должен добавить, что никто не может поймать «сбои» в коде C ++. Те не бросают исключения, но делают все, что им нравится. Когда вы видите сбой программы из-за разыменования нулевого указателя, она выполняет неопределенное поведение. Там нет std::null_pointer_exception. Попытка отловить исключения там не поможет.

Просто на тот случай, если кто-то читает эту ветку и думает, что может выяснить причину сбоя программы. Вместо этого следует использовать отладчик типа gdb.

56 голосов
/ 25 ноября 2008
try {
   // ...
} catch (...) {
   // ...
}

Обратите внимание, что ... внутри catch является настоящим многоточием, т.е. три точки.

Однако, поскольку исключения C ++ не обязательно являются подклассами базового Exception класса, нет никакого способа увидеть переменную исключения, которая выдается при использовании этой конструкции.

49 голосов
/ 10 июня 2014

Вот как вы можете перепроектировать тип исключения из catch(...), если вам нужно (может быть полезно при поиске неизвестного из сторонней библиотеки) с GCC:

#include <iostream>

#include <exception>
#include <typeinfo>
#include <stdexcept>

int main()
{
    try {
        throw ...; // throw something
    }
    catch(...)
    {
        std::exception_ptr p = std::current_exception();
        std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl;
    }
    return 1;
}

и если вы можете позволить себе Boost , вы можете сделать секцию catch еще проще (снаружи) и потенциально кроссплатформенной

catch (...)
{
    std::clog << boost::current_exception_diagnostic_information() << std::endl;
}
34 голосов
/ 11 октября 2009

невозможно (в C ++) перехватить все исключения в переносимой форме. Это связано с тем, что некоторые исключения не являются исключениями в контексте C ++. Это включает в себя такие вещи, как деление на ноль ошибок и другие. Можно взломать и, таким образом, получить возможность генерировать исключения, когда эти ошибки случаются, но это нелегко сделать и, конечно, нелегко получить правильные результаты в портативном виде.

Если вы хотите перехватить все исключения STL, вы можете сделать

try { ... } catch( const std::exception &e) { ... }

Что позволит вам использовать e.what(), который вернет const char*, что может рассказать вам больше о самом исключении. Это конструкция, которая больше всего напоминает конструкцию Java, о которой вы спрашивали.

Это не поможет вам, если кто-то настолько глуп, чтобы выдать исключение, которое не наследуется от std::exception.

21 голосов
/ 08 марта 2014

Короче говоря, используйте catch(...). Однако обратите внимание, что catch(...) предназначен для использования вместе с throw;, в основном:

try{
    foo = new Foo;
    bar = new Bar;
}
catch(...)       // will catch all possible errors thrown. 
{ 
    delete foo;
    delete bar;
    throw;       // throw the same error again to be handled somewhere else
}

Это правильный способ использования catch(...).

18 голосов
/ 20 сентября 2013

это можно сделать, написав:

try
{
  //.......
}
catch(...) // <<- catch all
{
  //.......
}

Но здесь есть очень незначительный риск: вы не можете найти точный тип ошибки, которая была выдана в блоке try, поэтому используйте этот тип catch, когда вы уверены, что независимо от того, что Тип исключения: программа должна сохраняться в порядке, определенном в блоке catch.

17 голосов
/ 25 ноября 2008

Вы можете использовать

catch(...)

но это очень опасно. В своей книге Отладка Windows Джон Роббинс рассказывает историю войны о действительно неприятной ошибке, которая была замаскирована командой catch (...). Вам гораздо лучше ловить конкретные исключения. Поймайте все, что, по вашему мнению, ваш блок try может разумно сгенерировать, но позвольте коду вывести исключение, если произойдет что-то действительно неожиданное.

12 голосов
/ 25 ноября 2008

Позвольте мне упомянуть об этом здесь: Java

try 
{
...
}
catch (Exception e)
{
...
}

НЕ МОЖЕТ ловить все исключения! У меня на самом деле было такое раньше и это провоцирует на безумство; Исключение происходит от Throwable. В буквальном смысле, чтобы поймать все, вы не хотите ловить исключения; Вы хотите поймать Throwable.

Я знаю, это звучит странно, но когда вы потратили несколько дней, пытаясь выяснить, откуда появилось «необработанное исключение» в коде, который был окружен блоком try… catch (Exception e) » это с тобой.

7 голосов
/ 23 апреля 2015

Хорошо, если вы хотите перехватить все исключения, например, для создания минидампа ...

Кто-то работал на Windows.

См. http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus В этой статье он объясняет, как он узнал, как перехватывать все виды исключений, и предоставляет код, который работает.

Вот список, который вы можете поймать:

 SEH exception
 terminate
 unexpected
 pure virtual method call
 invalid parameter
 new operator fault 
 SIGABR
 SIGFPE
 SIGILL
 SIGINT
 SIGSEGV
 SIGTERM
 Raised exception
C++ typed exception

И использование: CCrashHandler ch; ch.SetProcessExceptionHandlers (); // сделать это для одного потока ch.SetThreadExceptionHandlers (); // для каждого thred


По умолчанию это создает мини-дамп в текущем каталоге (crashdump.dmp)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...