С++ ловит все исключения

Существует ли С++-эквивалент Java

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

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

Ответ 1

try{
    // ...
} catch (...) {
    // ...
}

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

try{
    // ...
} catch (const std::exception& ex) {
    // ...
} catch (const std::string& ex) {
    // ...
} catch (...) {
    // ...
}

Ответ 2

Кто-то должен добавить, что в С++-коде нельзя "выловить" ошибки. Они не бросают исключений, но делают все, что им нравится. Когда вы видите сбой программы из-за разыменования нулевого указателя, он делает undefined behavior. Нет std::null_pointer_exception. Попытка поймать исключения не поможет там.

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

Ответ 3

try {
   // ...
} catch (...) {
   // ...
}

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

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

Ответ 4

Вот как вы можете реконструировать тип исключения из 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;
}

Ответ 5

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

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

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

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

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

Ответ 6

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

catch(...)

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

Ответ 7

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

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

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

Ответ 8

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

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

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

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

Ответ 9

Короче говоря, используйте 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(...).

Ответ 10

Ну, если вы хотите поймать все исключения, чтобы создать мини-накопитель, например...

Кто-то работал над 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


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

Ответ 11

Общий механизм обнаружения исключений окажется чрезвычайно полезным.

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

Что вы действительно хотите, это отладчик...

Ответ 12

  • Можете ли вы запустить приложение Java JNI из окна консоли (запустите его из командной строки java), чтобы узнать, есть ли какой-либо отчет о том, что могло быть обнаружено до сбоя JVM. При запуске непосредственно в качестве приложения окна Java вы можете пропускать сообщения, которые появлялись бы, если бы вы запускали из окна консоли.

  • Во-вторых, можете ли вы заглушить реализацию JNI DLL, чтобы показать, что методы в вашей DLL вводятся из JNI, вы возвращаетесь правильно и т.д.?

  • На всякий случай проблема с неправильным использованием одного из методов JNI-интерфейса из кода на С++, проверили ли вы, что некоторые простые примеры JNI компилируются и работают с вашей настройкой? Я имею в виду, в частности, использование методов JNI-интерфейса для преобразования параметров в собственные форматы С++ и преобразования результатов функции в типы Java. Полезно заглушить их, чтобы убедиться, что конверсии данных работают, и вы не сходитесь в COM-подобных вызовах в интерфейсе JNI.

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

Ответ 13

Для реальной проблемы неспособности правильно отлаживать программу, использующую JNI (или ошибка не появляется при запуске под отладчиком):

В этом случае часто помогает добавлять оболочки Java вокруг ваших вызовов JNI (т.е. все собственные методы являются частными, а ваши общедоступные методы в классе вызывают их), которые выполняют некоторую базовую проверку работоспособности (проверьте, что все "объекты" освобождены и "объекты" не используются после освобождения) или синхронизации (просто синхронизировать все методы из одной библиотеки DLL с экземпляром одного объекта). Пусть методы оболочки java регистрируют ошибку и генерируют исключение.

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

Если вы знаете причину, сохраните код в методах своей обертки, чтобы избежать этого. Лучше, чтобы ваши методы обертки выдавали исключения, чем ваш код JNI, сбой VM...