¿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 llama a través de jni. Un mecanismo genérico de captura de excepciones resultaría extremadamente útil.
Respuestas:
detectará 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ódigo heredados que requieren una reescritura), entonces no tiene un puntero de excepción con nombre 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:
fuente
Alguien debería agregar que no se pueden detectar "bloqueos" en el código C ++. Esos no arrojan excepciones, pero hacen lo que quieran. Cuando ve que un programa se bloquea debido a una desreferencia de puntero nulo, está haciendo un comportamiento indefinido. No hay
std::null_pointer_exception
. Intentar atrapar excepciones no ayudará allí.Solo por el caso, alguien está leyendo este hilo y piensa que puede obtener la causa del bloqueo del programa. En su lugar, se debe usar un depurador como gdb.
fuente
try { .. } catch(...) { ... }
captura usando la señal / sigaction, no lo llamaría "captura" :) Si en un controlador de señal, es relativamente difícil para el programador saber en qué parte del código ocurrió el bloqueo (estoy hablando sobre detectarlo programáticamente), en comparación con try / catch.Así es como puede realizar ingeniería inversa del tipo de excepción desde el interior
catch(...)
si lo necesita (puede ser útil al capturar datos desconocidos de una biblioteca de terceros) con GCC:y si puede permitirse el lujo de usar Boost , puede hacer que su sección de captura sea aún más simple (en el exterior) y potencialmente multiplataforma
fuente
Tenga en cuenta que el
...
interior delcatch
es una elipsis real, es decir. tres puntos.Sin embargo, debido a que las excepciones de C ++ no son necesariamente subclases de una
Exception
clase base , no hay ninguna forma de ver realmente la variable de excepción que se genera al usar esta construcción.fuente
catch
especificador del marcador de posición de código existente en un comentario (// ...
) que obviamente no es la sintaxis de C ++.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, obtener la capacidad de lanzar excepciones cuando ocurren estos errores, pero no es fácil de hacer y ciertamente no es fácil hacerlo de manera portátil.
Si desea capturar todas las excepciones STL, puede hacerlo
Lo que le permitirá usar
e.what()
, lo que devolverá unconst char*
, que puede darle más información sobre la excepción en sí. Esta es la construcción que se asemeja a la construcción de Java, que más preguntaste.Esto no te ayudará si alguien es lo suficientemente estúpido como para lanzar una excepción que no hereda
std::exception
.fuente
En resumen, uso
catch(...)
. Sin embargo, tenga en cuenta quecatch(...)
está destinado a ser utilizado conjuntamente conthrow;
básicamente:Esta es la forma correcta de usar
catch(...)
.fuente
Foo
el destructor? Pensé que ese era el objetivo de RAII. Sin embargo, si necesita un puntero a un enFoo
lugar de simplemente crearloFoo
en la pila, entonces necesitará envolver el puntero en otra cosa que se declare en la pila.es posible hacer esto escribiendo:
Pero aquí hay un riesgo muy poco notable: no puede encontrar el tipo exacto de error que se ha arrojado en el
try
bloque, así que use este tipo decatch
cuando esté seguro de que no importa cuál sea el tipo de excepción, el programa debe persistir en la forma definida en elcatch
bloque.fuente
Puedes usar
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 (...). Es mucho mejor capturar excepciones específicas. Captura lo que creas que tu bloque de prueba podría lanzar razonablemente, pero deja que el código arroje una excepción más arriba si sucede algo realmente inesperado.
fuente
Permítanme mencionar esto aquí: el Java
¡NO puede atrapar todas las excepciones! De hecho, he tenido este tipo de cosas antes, y es increíblemente provocativo; La excepción deriva de Throwable. Entonces, literalmente, para atrapar todo, NO desea atrapar excepciones; quieres atrapar a Throwable.
Sé que suena quisquilloso, pero cuando pasaste varios días tratando de descubrir de dónde vino la "excepción no descubierta" en el código que estaba rodeado por un bloque try ... catch (Exception e) ", se queda con tú.
fuente
catch(Exception)
posible que no capture todas las excepciones en Java, lo está mezclando con C # ... Java =catch(Thowable)
, C # =catch(Exception)
. No los confundas.CoderMalfunctionError
(que en realidad es una verdaderaError
subclase de Java ... aunque no significa cómo suena)Bueno, si desea capturar todas las excepciones para crear un minivolcado, por ejemplo ...
Alguien hizo el trabajo en Windows.
Ver 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:
Y el uso: CCrashHandler ch; ch.SetProcessExceptionHandlers (); // hacer esto para un hilo ch.SetThreadExceptionHandlers (); // por cada thred
Por defecto, esto crea un minivolcado en el directorio actual (crashdump.dmp)
fuente
Dudoso. Ya sabes que tu código está roto porque está fallando. Comer excepciones puede enmascarar esto, pero eso probablemente solo dará como resultado errores aún más desagradables y sutiles.
Lo que realmente quieres es un depurador ...
fuente
¿Puede ejecutar su aplicación Java que utiliza JNI desde una ventana de la consola? Cuando se ejecuta directamente como una aplicación de ventana Java, es posible que le falten mensajes que aparecerían si se ejecutara desde una ventana de consola.
En segundo lugar, ¿puede bloquear la implementación de su DLL JNI para mostrar que los métodos en su DLL se ingresan desde JNI, está regresando correctamente, etc.?
En caso de que el problema sea con el uso incorrecto de uno de los métodos de la interfaz JNI del código C ++, ¿ha verificado que algunos ejemplos simples de JNI compilan y funcionan con su configuración? Estoy pensando en particular en utilizar los métodos de la interfaz JNI para convertir parámetros a formatos nativos de C ++ y convertir los resultados de las funciones en tipos Java. Es útil agruparlos para asegurarse de que las conversiones de datos funcionen y que no se vuelva loco en las llamadas tipo COM a la interfaz JNI.
Hay otras cosas que verificar, pero es difícil sugerir alguna sin saber más acerca de cuáles son sus métodos nativos de Java y qué está tratando de hacer la implementación de JNI de ellos. No está claro que detectar una excepción del nivel de código C ++ esté relacionado con su problema. (Puede usar la interfaz JNI para volver a lanzar la excepción como Java, pero de lo que proporciona no está claro si esto va a ayudar).
fuente
Para el verdadero problema de no poder depurar correctamente un programa que usa JNI (o el error no aparece cuando se ejecuta bajo un depurador):
En este caso, a menudo es útil 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 comprobación básica de sanidad (verifique que todos los "objetos" estén liberados y "objetos" no se usan después de la liberación) o la sincronización (solo sincronice todos los métodos de una DLL a una sola instancia de objeto). Deje que los métodos java wrapper registren el error y generen una excepción.
A menudo, esto ayudará a encontrar el error real (que sorprendentemente se encuentra principalmente en el código Java que no obedece a la semántica de las funciones llamadas que causan algunas liberaciones dobles desagradables o similares) más fácilmente que tratar de depurar un programa 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 sus métodos de envoltura arrojen excepciones que su código JNI bloquee la VM ...
fuente
Bueno, esto realmente depende del entorno del compilador. gcc no los atrapa. Visual Studio y el último Borland que usé lo hicieron.
Entonces, la conclusión sobre los bloqueos es que depende de la calidad de su entorno de desarrollo.
La especificación de C ++ dice que catch (...) debe detectar cualquier excepción, pero no en todos los casos.
Al menos por lo que intenté.
fuente
Se consciente
captura solo excepciones de nivel de idioma, otras excepciones / errores de bajo nivel como
Access Violation
ySegmentation Fault
no se detectarán.fuente