c++ - try - std::exception
C++ captura todas las excepciones (14)
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 resultará en errores aún más desagradables y sutiles.
Lo que realmente quieres es un depurador ...
¿Hay un equivalente en C ++ de Java?
try {
...
}
catch (Throwable t) {
...
}
Estoy intentando 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 parece correcto en las pruebas unitarias y solo parece fallar cuando se llama a través de jni. Un mecanismo genérico de captura de excepciones sería extremadamente útil.
¿Puede ejecutar su aplicación Java utilizando JNI desde una ventana de consola (ejecutarlo desde una línea de comando java) para ver si hay algún informe de lo que pudo haber sido detectado antes de que se bloquee la JVM? Cuando se ejecuta directamente como una aplicación de ventana Java, es posible que falten mensajes que aparecerían si se ejecutara desde una ventana de la consola.
En segundo lugar, ¿puede aplazar la implementación de JNI DLL para mostrar que los métodos en su DLL se están ingresando desde JNI, está regresando correctamente, etc.?
En caso de que el problema sea el uso incorrecto de uno de los métodos de interfaz JNI del código C ++, ¿ha verificado que algunos ejemplos simples de JNI se compilan y funcionan con su configuración? Estoy pensando, en particular, en utilizar los métodos de interfaz JNI para convertir parámetros a formatos C ++ nativos y convertir los resultados de las funciones en tipos Java. Es útil eliminarlos para asegurarse de que las conversiones de datos estén funcionando y de que no vaya a fallar en las llamadas de tipo COM a la interfaz JNI.
Hay otras cosas para verificar, pero es difícil sugerirlas sin saber más acerca de cuáles son sus métodos Java nativos y qué es lo que la implementación de JNI está tratando de hacer. No está claro si la captura de una excepción del nivel de código de C ++ está relacionada con su problema. (Puede usar la interfaz JNI para volver a emitir la excepción como Java, pero no está claro por lo que proporcione que esto va a ayudar).
Alguien debería agregar que uno no puede atrapar "bloqueos" en el código C ++. Esos no lanzan excepciones, pero hacen lo que les gusta. Cuando ves que un programa falla debido a una falta de referencia de puntero nulo, está haciendo un comportamiento indefinido. No hay std::null_pointer_exception
. Tratar de atrapar excepciones no ayudará allí.
Solo en el caso de que alguien esté leyendo este hilo y piense que puede obtener la causa de los bloqueos del programa. Debería usarse un depurador como gdb en su lugar.
Así es como se puede aplicar ingeniería inversa al tipo de excepción desde catch(...)
caso de que necesite (puede ser útil cuando se captura un desconocido de una biblioteca de terceros) con 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;
}
y si puede permitirse usar Boost , puede hacer que su sección de captura sea aún más simple (en el exterior) y potencialmente multiplataforma
catch (...)
{
std::clog << boost::current_exception_diagnostic_information() << std::endl;
}
Bueno, esto realmente depende del entorno del compilador. gcc no captura estos. Visual Studio y el último Borland que usé lo hicieron.
Entonces, la conclusión acerca de los bloqueos es que depende de la calidad de su entorno de desarrollo.
La especificación de C ++ dice que catch (...) debe capturar cualquier excepción, pero no lo hace en todos los casos.
Al menos por lo que intenté.
Bueno, si desea capturar todas las excepciones para crear un minidump, 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 capturar:
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 (); // haz esto para un hilo ch.SetThreadExceptionHandlers (); // por cada thred
De forma predeterminada, esto crea un minidump en el directorio actual (crashdump.dmp)
En resumen, utilizar catch(...)
. Sin embargo, tenga en cuenta que la catch(...)
debe utilizarse junto con el 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(...)
.
Es posible hacerlo escribiendo:
try
{
//.......
}
catch(...) // <<- catch all
{
//.......
}
Pero hay un riesgo muy notable aquí: no 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 no importa cuál sea el tipo de excepción, el programa Debe persistir en la forma definida en el bloque catch
.
Para el problema real de no poder depurar correctamente un programa que usa JNI (o el error no aparece al ejecutarlo en un depurador):
En este caso, a menudo es útil agregar envoltorios de 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 realizan algunas comprobaciones básicas (verifique que todos los "objetos" estén liberados y "objetos"). no se utilizan después de la liberación) o sincronización (solo sincronice todos los métodos de una DLL a una sola instancia de objeto). Deje que los métodos de envoltura de Java registren el error y lancen una excepción.
A menudo, esto ayudará a encontrar el error real (que, sorprendentemente, se encuentra principalmente en el código de Java que no obedece a la semántica de las funciones llamadas que causan algunas descargas dobles desagradables o similares) más fácilmente que intentar depurar un programa Java masivamente paralelo en un depurador nativo ...
Si conoce la causa, mantenga el código en los métodos de envoltura que lo evitan. Es mejor que sus métodos de envoltura generen excepciones que su código JNI bloquee la máquina virtual ...
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 que sucedieron antes, y es insoportable; La excepción se deriva de Throwable. Así que, literalmente, para atrapar todo, usted NO quiere atrapar Excepciones; quieres atrapar Throwable.
Sé que suena nítido, pero cuando pasas varios días intentando averiguar de dónde proviene la "excepción no detectada" en el código que estaba rodeado por un bloque try ... catch (Exception e) ", se mantiene fiel a tú.
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 estaba enmascarado por un comando catch (...). Es mucho mejor atrapar excepciones específicas. Capture lo que crea que su bloque try podría lanzar razonablemente, pero deje que el código arroje una excepción más arriba si ocurre algo realmente inesperado.
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 división por cero errores y otros. Es posible piratear y así obtener la posibilidad de lanzar excepciones cuando ocurren estos errores, pero no es fácil de hacer y, ciertamente, no es fácil hacerlo correctamente de manera portátil.
Si desea capturar todas las excepciones de 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 acerca de la excepción. Esta es la construcción que se asemeja a la construcción de Java, la que más preguntaste.
Esto no te ayudará si alguien es lo suficientemente estúpido como para lanzar una excepción que no hereda de std::exception
.
try {
// ...
} catch (...) {
// ...
}
Tenga en cuenta que el ...
dentro de la catch
es una elipsis real, es decir. tres puntos.
Sin embargo, debido a que las excepciones de C ++ no son necesariamente subclases de una clase de Exception
base, no hay ninguna manera de ver realmente la variable de excepción que se produce cuando se usa esta construcción.
try{
// ...
} catch (...) {
// ...
}
capturará todas las excepciones de C ++, pero debe considerarse 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 con nombre para usar para recibir 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 (...) {
// ...
}