sistema obtener fecha ejemplo dev c++ debugging exception gdb inspection

obtener - ¿Cómo obtengo el valor y el tipo de la excepción actual en C++ usando gdb?



obtener fecha del sistema en dev c++ (3)

gdb permite capturar excepciones cuando se lanzan y cuando se capturan. Pero a veces la línea en la que se lanza una excepción no tiene símbolos, o se activa un punto de interrupción durante el manejo de la excepción. ¿Cómo inspecciono el valor de la excepción actual?


Las respuestas anteriores fueron correctas cuando se escribieron (en 2013), pero desde entonces gdb y libstdc ++ han cambiado.

libstdc ++ ahora tiene algunos ganchos que permiten a gdb interactuar de forma más agradable con el sistema de excepciones. En particular, ahora hay suficiente información expuesta para gdb para proporcionar una variable de conveniencia $_exception al usuario. Esta variable contiene la excepción que se está lanzando. Solo es válido exactamente en el lugar donde se captura la excepción; que se puede parar en la catch catch .

Vea la página del manual para más detalles.


Respuesta corta: no puede porque la mayoría del trabajo de manejo de excepciones se realiza fuera de su programa y, por lo tanto, está fuera del alcance de gdb.

Respuesta explicada:

A veces la línea en la que se lanza una excepción no tiene símbolos.

Si el binario que está depurando no tiene símbolos de depuración, entonces el binario probablemente se elimina y no podrá encontrar mucho sobre los tipos / valores de nada.

¿Cómo inspecciono el valor de la excepción actual?

Creo que estás asumiendo que una excepción es una característica de lenguaje que gdb puede inspeccionar; de hecho, una excepción en C ++ es una combinación de características de C ++ como lenguaje, de libc ++ y el ABI. E incluso puede haber más de una sola excepción activa actual.

Al igual que UpAndAdam señala que puede establecer un punto de interrupción en un bloque catch con un especificador de tipo y luego inspeccionar ese elemento, pero sospecho que su problema es en los casos en que encuentre un "catch (...)". En esos casos, no podrá aprender mucho sobre la excepción actual a menos que vaya a profundizar en la implementación del manejo de excepciones.

Con una descripción muy breve e incompleta, podríamos decir que para lanzar una excepción:

  1. Su programa llamará a libc ++ para generar una excepción.
  2. libc ++ llamará "desenrollar" en glibc para comenzar a desenrollar la pila
  3. desenrollar devolverá una "función de personalidad" de libc ++ para cada marco de pila (básicamente, cada llamada de función en la pila)
  4. la función de personalidad decidirá de alguna manera si el marco de pila actual puede o no puede manejar esta excepción
  5. Si la excepción puede ser manejada, el bloque catch será ejecutado.

Ahora, es difícil hablar de detalles porque una gran cantidad de excepciones depende de su cadena de herramientas (compilador, plataforma, arquitectura, libc ++, etc.) pero en la mayoría de los casos un "catch (...)" ni siquiera recibirá la excepción original como argumento En cualquier caso, para responder de alguna manera a tu pregunta: en gcc con gnu''s libc ++ puedes intentar algo como esto:

  1. Obtener un libc ++ con símbolos de depuración
  2. Establezca un punto de interrupción en __gxx_personality_v0 (que se llama la función de personalidad). Se llamará a esta función para determinar si un marco de pila (una llamada de función, básicamente) tiene un bloque catch adecuado para manejar la excepción
  3. En la función de personalidad podrás encontrar un puntero a _Unwind_Exception, que es una envoltura para tu excepción real
  4. Obtenga la información de tipo para su excepción como esta: __cxa_exception * exception_header = (__cxa_exception *) (unwind_exception + 1) -1; std :: type_info * thrown_exception_type = exception_header-> exceptionType;
  5. Obtendrá un tipo de excepción que luego puede buscar con el resto del RTTI definido para su código

En cualquier caso, es probable que deba pasar bastante tiempo tratando de comprender cómo se implementa el manejo de excepciones en su plataforma. Si desea leer un poco más sobre el manejo de excepciones, dediqué algún tiempo a escribir sobre el tema @ http://monoinfinito.wordpress.com/series/exception-handling-in-c/ . No es una fuente oficial pero tiene enlaces a las especificaciones de cada parte involucrada en el manejo de una excepción.


Actualizado

Aquí hay algo de información del Manual de GDB

Actualmente hay algunas limitaciones para el manejo de excepciones de C ++ (captura y captura) en gdb:

Si llama a una función interactivamente, gdb normalmente le devuelve el control cuando la función ha terminado de ejecutarse. Sin embargo, si la llamada genera una excepción, la llamada puede omitir el mecanismo que le devuelve el control y hacer que su programa se cancele o simplemente continúe ejecutándose hasta que llegue a un punto de interrupción, reciba una señal de que gdb está escuchando o sale. Este es el caso incluso si establece un punto de captura para la excepción; Los puntos de captura en las excepciones están deshabilitados dentro de las llamadas interactivas. No puede generar una excepción interactivamente. No puede instalar un controlador de excepciones de forma interactiva. A veces, la captura no es la mejor manera de depurar el manejo de excepciones: si necesita saber exactamente dónde se produce una excepción, es mejor detenerse antes de llamar al controlador de excepciones, ya que de esa manera puede ver la pila antes de que se produzca el desenrollamiento. Si establece un punto de interrupción en un controlador de excepciones, puede que no sea fácil averiguar dónde se generó la excepción.

Para detenerse justo antes de llamar a un controlador de excepciones, necesita tener algún conocimiento de la implementación. En el caso de gnu C ++, se generan excepciones llamando a una función de biblioteca llamada __raise_exception que tiene la siguiente interfaz ANSI C:

/* addr is where the exception identifier is stored. id is the exception identifier. */ void __raise_exception (void **addr, void *id); To make the debugger catch all exceptions before any stack unwinding takes place,

establezca un punto de interrupción en __raise_exception (vea Puntos de interrupción; Puntos de vigilancia; y Excepciones).

Que dicho

Depende del código y de dónde estés en la pila. Si realmente atrapó la excepción como en:

try { .... } catch (std::exception &e) { //do stuff }

Probablemente podría intentar imprimir e.what() , o mirar a los miembros de la excepción. Si lo captaste como (...), entonces no estoy seguro de lo que podrías reunir.

Otra cosa que puedes hacer es capturar ''lanzar'' en gdb y atrapar ''captura'' también si realmente quieres seguir todo el flujo.

gdb> catch catch gdb> catch throw

De esta manera obtendrá un punto de interrupción justo antes de que se lancen las excepciones y, en el momento en que se detecten, puede caminar por la pila para obtener más información sobre lo que estaba sucediendo. Incluso si se encuentra en otro punto de quiebre, debería poder subir la pila (usar hacia arriba o hacia abajo) para obtener el marco en el que se ve la excepción.