C ++ detecta todas las excepciones

¿Hay un equivalente en c ++ de Java?

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

Estoy tratando de depurar el código Java / jni que llama a las funciones nativas de Windows y la máquina virtual sigue fallando. El código nativo aparece bien en las pruebas unitarias y solo parece bloquearse cuando se lo llama a través de jni. Un mecanismo genérico de captura de excepciones sería extremadamente útil.

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

capturará todas las excepciones de C ++, pero se debe considerar un mal diseño. Puede usar el nuevo mecanismo current_exception de c ++ 11, pero si no tiene la capacidad de usar c ++ 11 (sistemas de códigos heredados que requieren una reescritura), entonces no tiene un puntero de excepción nombrado para usar para obtener un mensaje o nombre . Es posible que desee agregar cláusulas de captura separadas para las diversas excepciones que puede capturar y solo capturar todo en la parte inferior para registrar una excepción inesperada. P.ej:

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

Alguien debería agregar que uno no puede atrapar “lockings” en el código C ++. Esos no arrojan excepciones, pero hacen lo que les gusta. Cuando ve un progtwig bloquearse por decir una desreferencia de puntero nulo, está haciendo undefined behavior . No hay std::null_pointer_exception . Tratar de atrapar excepciones no ayudará allí.

Solo para el caso, alguien está leyendo este hilo y cree que puede obtener la causa de los lockings del progtwig. En su lugar, debería usarse un depurador como gdb.

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

Tenga en cuenta que ... dentro de la catch es una verdadera elipsis, es decir. tres puntos.

Sin embargo, dado que las excepciones de C ++ no son necesariamente subclases de una clase de Exception base, no hay ninguna forma de ver realmente la variable de excepción que se lanza al usar esta construcción.

Esta es la forma en que puede aplicar ingeniería inversa al tipo de excepción desde catch(...) caso de que lo necesite (puede ser útil cuando capture desconocido de una biblioteca de terceros) con GCC:

 #include  #include  #include  #include  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; } 

y si puede permitirse usar Boost , puede hacer que su sección de capturas sea aún más simple (en el exterior) y potencialmente multiplataforma

 catch (...) { std::clog < < boost::current_exception_diagnostic_information() << std::endl; } 

no es posible (en C ++) capturar todas las excepciones de manera portátil. Esto se debe a que algunas excepciones no son excepciones en un contexto de C ++. Esto incluye cosas como la división por cero errores y otros. Es posible hackear y, por lo tanto, tener la capacidad de lanzar excepciones cuando se producen estos errores, pero no es fácil de hacer y, desde luego, no es fácil hacerlo de manera portátil.

Si quiere capturar todas las excepciones STL, puede hacer

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

Lo que le permitirá usar e.what() , que devolverá un const char* , que puede e.what() más información sobre la excepción en sí. Esta es la construcción que se asemeja a la construcción de Java, sobre la que preguntaste más.

Esto no lo ayudará si alguien es lo suficientemente estúpido como para lanzar una excepción que no hereda de std::exception .

Puedes usar

 catch(...) 

pero eso es muy peligroso. En su libro Debugging Windows , John Robbins cuenta una historia de guerra sobre un error realmente desagradable que fue enmascarado por un comando catch (…). Estás mucho mejor sin detectar excepciones específicas. Captura lo que creas que tu bloque try podría arrojar razonablemente, pero deja que el código arroje una excepción más arriba si ocurre algo realmente inesperado.

es posible hacer esto escribiendo:

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

Pero aquí hay un riesgo muy poco notable: no se puede encontrar el tipo exacto de error que se ha lanzado en el bloque try , así que use este tipo de catch cuando esté seguro de que, sin importar el tipo de excepción, el progtwig debe persistir en la forma definida en el bloque catch .

En resumen, use catch(...) . Sin embargo, tenga en cuenta que catch(...) está destinado a ser utilizado en conjunción con throw; básicamente:

 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 } 

Esta es la forma correcta de usar catch(...) .

Permítanme mencionar esto aquí: el Java

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

¡NO puede atrapar todas las excepciones! De hecho, he tenido este tipo de cosas antes, y es insidiosamente provocador; La excepción se deriva de Throwable. Así que literalmente, para atrapar todo, NO QUIERES atrapar excepciones; quieres atrapar Throwable.

Sé que suena insignificante, pero cuando has pasado varios días tratando de averiguar de dónde vino la “excepción no detectada” en el código que estaba rodeado por un bloque try … catch (Exception e) “, se pega con tú.

Bueno, si quieres ver todas las excepciones para crear un minivolcado, por ejemplo …

Alguien hizo el trabajo en Windows.

Consulte http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus En el artículo, explica cómo descubrió cómo detectar todo tipo de excepciones y proporciona un código que funciona.

Aquí está la lista que puedes atrapar:

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

Y el uso: CCrashHandler ch; ch.SetProcessExceptionHandlers (); // hacer esto para un hilo ch.SetThreadExceptionHandlers (); // por cada hilo

Por defecto, esto crea un minivolcado en el directorio actual (crashdump.dmp)

Un mecanismo genérico de captura de excepciones sería extremadamente útil.

Dudoso. Ya sabes que tu código está roto, porque está fallando. Comer excepciones puede enmascarar esto, pero eso probablemente solo resultará en errores aún más sutiles y más sutiles.

Lo que realmente quieres es un depurador …

  1. ¿Puede ejecutar su aplicación Java que usa JNI desde una ventana de la consola (iniciarla desde una línea de comando java) para ver si hay algún informe de lo que se pudo haber detectado antes de que se estrellara la JVM? Cuando se ejecuta directamente como una aplicación de ventana de Java, es posible que le falten mensajes que aparecerían si ejecutara desde una ventana de consola en su lugar.

  2. En segundo lugar, ¿puede resguardar su implementación de DLL JNI para mostrar que los métodos en su DLL se están ingresando desde JNI, está regresando correctamente, etc.?

  3. En caso de que el problema sea con un uso incorrecto de uno de los métodos de interfaz JNI del código C ++, ¿ha verificado que algunos ejemplos JNI simples comstackn y trabajan con su configuración? Estoy pensando en utilizar los métodos de la interfaz JNI para convertir parámetros en formatos nativos de C ++ y convertir los resultados de las funciones en tipos de Java. Es útil resguardarlos para asegurarse de que las conversiones de datos funcionen y no se descontrole en las llamadas tipo COM en la interfaz JNI.

  4. Hay otras cosas para verificar, pero es difícil sugerir cualquiera sin saber más acerca de cuáles son los métodos nativos de Java y qué está tratando de hacer la implementación de JNI. No está claro que la captura de una excepción del nivel de código C ++ esté relacionada con su problema. (Puede usar la interfaz JNI para volver a lanzar la excepción como Java, pero no está claro por lo que usted proporciona que esto ayude).

Por el problema real de no poder depurar correctamente un progtwig que usa JNI (o el error no aparece cuando se ejecuta bajo un depurador):

En este caso, a menudo ayuda agregar envoltorios Java alrededor de sus llamadas JNI (es decir, todos los métodos nativos son privados y sus métodos públicos en la clase los llaman) que hacen una verificación de cordura básica (verifique que todos los “objetos” estén libres y “objetos” no se utilizan después de la liberación) o la sincronización (simplemente sincronice todos los métodos de una DLL a una única instancia de objeto). Deje que los métodos de envoltura de java registren el error y generen una excepción.

Esto a menudo ayudará a encontrar el error real (que sorprendentemente es principalmente en el código de Java que no obedece a la semántica de las funciones llamadas causando algunas desagradables dobleces o similares) más fácilmente que intentar depurar un progtwig Java masivamente paralelo en un depurador nativo …

Si conoce la causa, mantenga el código en sus métodos de envoltura que lo evite. Es mejor que los métodos de contenedor arrojen excepciones que el código JNI bloquee la VM …

Bueno, esto realmente depende del entorno del comstackdor. gcc no los detecta. Visual Studio y el último Borland que utilicé lo hicieron.

Entonces, la conclusión sobre los fallos es que depende de la calidad de su entorno de desarrollo.

La especificación C ++ dice que catch (…) debe capturar cualquier excepción, pero no en todos los casos.

Al menos por lo que probé.