Вопрос по exception, c++ – Есть ли способ получить хоть какую-то информацию по улову (…)?

4

Есть ли способ получить хоть какую-то информацию?

<code>...
catch(...)
{
  std::cerr << "Unhandled exception" << std::endl;
}
</code>

У меня есть последнее средство вокруг всего моего кода. Было бы лучше позволить ему рухнуть, потому что тогда я, по крайней мере, смогу получить отчет о сбое?

Обратите внимание, что GCC имеет заголовок cxxabi.h, который содержит __cxa_current_exception_type (); extern "C" функция, которая возвращает объект std :: type_info, и __cxa_demangle, который разбирает. С этими двумя функциями, как указано в Codesourcery.com / государственные / CXX-аби / abi.html, вы можете напечатать тип исключения в GCC. Johannes Schaub - litb

Ваш Ответ

5   ответов
0

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

Имейте в виду, вам не нужно падать, чтобы создать отчет о сбое. Есть API для генерации мини-дампа, и вы можете сделать это в своем обработчике SEH.

9

нет никакого способа. Попробуйте сделать все ваши классы исключений производными от одного класса, напримерstd::exception, а потом поймай это.

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

4

используя gdb или другой отладчик. Скажите отладчику, чтобы он остановился, если выброшено какое-либо исключение (в gdb команда прикольнаяcatch throw). Тогда вы увидите не только тип исключения, но и откуда оно.

Еще одна идея - закомментироватьcatch (...) и пусть ваша среда выполнения завершит работу вашего приложения и, надеюсь, расскажет вам больше об исключении.

Как только вы выясните, что является исключением, вы должны попытаться заменить или дополнить его чем-то, что происходит отstd::exception. Того, чтобыcatch (...) совсем не здорово.

Если вы используете GCC или Clang, вы также можете попробовать__cxa_current_exception_type()->name(), чтобы получить имя текущего типа исключения.

1

Да, но насколько это полезно, можно обсуждать:

#include <exception>
#include <iostream>
using namespace std;

int f() {
    throw "message";
}

int main() {
    try {
        f();
    }
    catch ( ... ) {
        try {
            throw;
        }
        catch( const char *  s ) {
            cout << "caught " << s << endl;
        }
    }
}

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

но это не ловит бросок 7 Net Citizen
Возможно - но первоначальный вопрос был о извлечении «некоторой» информации из улова (...), и это единственный известный мне метод для этого. anon
0

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

Эту идею можно распространить на динамический реестр типов исключений, если вы хотите, с чем вам следует позаботиться, чтобы убедиться, что список находится в наиболее производном или наименее производном порядке (требуетсямног перебрасывания и ловли при регистрации!)

#include <iostream>
#include <stdexcept>
#include <exception>
#include <typeinfo>
#include <system_error>

namespace detail {
    // a function which compares the current exception against a list of exception types terminated
    // with a void type
    // if a match is made, return the exception (mangled) class name and the what() string.
    // note that base classes will be caught if the actual class is not mentioned in the list
    // and the list must be in the order of most-derived to least derived
    //
    template<class E, class...Rest>
    std::string catcher_impl()
    {
        try
        {
            std::rethrow_exception(std::current_exception());
        }
        catch(const E& e)
        {
            bool is_exact = typeid(E) == typeid(e);
            return std::string(typeid(E).name()) + (is_exact ? "(exact)" : "(base class)") + " : " + e.what();
        }
        catch(...)
        {
            return catcher_impl<Rest...>();
        }
        return "unknown";
    }

    // specialise for end of list condition
    template<> std::string catcher_impl<void>()
    {
        return "unknown exception";
    }
}

// catcher interface
template<class...Es>
std::string catcher()
{
    return detail::catcher_impl<Es..., void>();
}

// throw some exception type
// and then attempt to identify it using the type list available
//
template<class E>
void test(E&& ex)
{
    try
    {
        throw std::forward<E>(ex);
    }
    catch(...)
    {
        std::cout << "exception is: "
        << catcher<std::invalid_argument, std::system_error, std::runtime_error, std::logic_error>()
        << std::endl;
    }
}

int main()
{
    test(std::runtime_error("hello world"));
    test(std::logic_error("my logic error"));
    test(std::system_error(std::make_error_code(std::errc::filename_too_long)));
    test(std::invalid_argument("i don't like arguments"));

    struct my_runtime_error : std::runtime_error
    {
        using std::runtime_error::runtime_error;
    };
    test(my_runtime_error("an unlisted error"));
}

пример вывода:

exception is: St13runtime_error(exact) : hello world
exception is: St11logic_error(exact) : my logic error
exception is: NSt3__112system_errorE(exact) : File name too long
exception is: St16invalid_argument(exact) : i don't like arguments
exception is: St13runtime_error(base class) : an unlisted error

Похожие вопросы