C ++ получить описание исключения, пойманного в блоке catch (...) - PullRequest
23 голосов
/ 04 сентября 2010

могу ли я получить описание исключения, пойманного

catch(...)

блок? что-то вроде .what () из std :: exception.

Ответы [ 6 ]

40 голосов
/ 04 сентября 2010

Существует один трюк, который вы можете использовать:

catch(...) {
    handle_exception();
}

void handle_exception() {
    try {
        throw;
    } catch (const std::exception &e) {
        std::cout << e.what() << "\n";
    } catch (const int i) {
        std::cout << i << "\n";
    } catch (const long l) {
        std::cout << l << "\n";
    } catch (const char *p) {
        std::cout << p << "\n";
    } catch (...) {
        std::cout << "nope, sorry, I really have no clue what that is\n";
    }

и т. Д. Для стольких различных типов, сколько вы думаете, может быть выброшено.Если вы действительно ничего не знаете о том, что может быть выброшено, то даже этот второй-последний неверен, потому что кто-то может выбросить char*, который не указывает на строку с нулевым символом в конце.

Обычно этоплохая идея бросать что-либо, что не является std::exception или производным классом.Причина, по которой существует std::exception, заключается в том, что каждый может бросать и ловить предметы, с которыми он может сделать что-то полезное.В игрушечной программе, где вы просто хотите выбраться оттуда и даже не можете добавить стандартный заголовок, хорошо, возможно, выведите int или строковый литерал.Я не думаю, что сделал бы эту часть формального интерфейса.Любые исключения, которые вы выбрасываете, являются частью вашего официального интерфейса, даже если вы как-то забыли их документировать.

5 голосов
/ 04 сентября 2010

Этот блок может поймать int, или const char *, или что-нибудь еще.Как может компилятор знать, как описать что-то, когда он ничего не знает об этом?Если вы хотите получить информацию из исключения, вы должны знать тип.

4 голосов
/ 04 сентября 2010

Если вы знаете, что бросаете только std :: исключение или подклассы, попробуйте

catch(std::exception& e) {...e.what()... }

В противном случае, как писал DeadMG, поскольку вы можете выбросить (почти) все, вы не сможете предположить, что вы поймали.

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

catch(my::specialException& e) {
      // I know what happened and can handle it
      ... handle special case
      }
catch(my::otherSpecialException& e) {
      // I know what happened and can handle it
      ... handle other special case
      }
catch(std::exception& e) {
      //I can at least do something with it
      logger.out(e.what());
      }
catch(...) {
     // something happened that should not have 
     logger.out("oops");
     }
3 голосов
/ 18 сентября 2014

Начиная с C ++ 11 вы можете захватить текущее исключение с помощью указателя:

std::exception_ptr p;     // default initialization is to nullptr

try {
      throw 7;
}
catch(...)
{
     p = std::current_exception();
}

Это ведет себя как умный указатель; если хотя бы один указатель указывает на объект исключения, он не уничтожается.

Позже (возможно, даже в другой функции) вы можете действовать аналогично текущему топ-ответу:

try {
    if ( p )
        std::rethrow_exception(p);
}
catch(int x)
{

}
catch(std::exception &y)
{
}
2 голосов
/ 18 сентября 2014

Цитирование Боба

#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;
}
2 голосов
/ 04 сентября 2010

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

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

Помните, что исключения us предназначены для получения информации о том, что пошло не так.Таким образом, каждый бит информации помогает в этом отношении ..

...