vida triangulo significado quiromancia palma matrimonio mano lineas linea leer las destino dela cómo amor c++ exception exception-handling

c++ - triangulo - ¿Cómo saber la línea exacta de código donde se ha producido una excepción?



significado de las lineas dela mano del amor (8)

Si genero una excepción yo mismo, puedo incluir cualquier información en la excepción: una cantidad de línea de código y nombre del archivo fuente. Algo como esto:

throw std::exception("myFile.cpp:255");

Pero, ¿qué pasa con las excepciones no controladas o con excepciones que no generé yo?


Además de usar una clase personalizada con una macro, como sugiere Frank Krueger, para sus propias excepciones, podría interesarle echar un vistazo al mecanismo estructurado de manejo de excepciones (usted está programando bajo Windows, ¿no?)
Comprobar el manejo de excepciones estructuradas en MSDN


Creo que un rastro de pila debería llevarlo al grano.


Encontré 2 soluciones, pero ninguna es completamente satisfactoria:

  1. Si llama a std::set_terminate , desde allí puede imprimir la pila de llamadas desde el lanzamiento de excepción de terceros. Desafortunadamente, no hay forma de recuperarse de un manejador de terminación, y por lo tanto su aplicación morirá.

  2. Si llama a std::set_unexpected , entonces necesita declarar tantas como sea posible de sus funciones con throw(MyControlledException) , de modo que cuando lo lanzan debido a funciones llamadas por terceros, su unexpected_handler podrá darle un grano fino idea de dónde arrojó su aplicación.


Hay varias posibilidades para descubrir dónde se lanzó la excepción:

Usar macros de compilación

Usar macros __FILE__ y __LINE__ en la ubicación del lanzamiento (como ya lo han mostrado otros comentaristas), ya sea utilizándolos en excepciones estándar como texto, o como argumentos separados para una excepción personalizada:

Ya sea uso

throw std::runtime_error(msg " at " `__FILE__` ":" `__LINE__`);

o tirar

class my_custom_exception { my_custom_exception(const char* msg, const char* file, unsigned int line) ...

Tenga en cuenta que incluso al compilar para Unicode (en Visual Studio), FILE se expande a una cadena de un solo byte. Esto funciona en depuración y liberación. Desafortunadamente, los nombres de los archivos de origen con excepciones de lanzamiento de código se colocan en el ejecutable de salida.

Stack Walking

Averigua la ubicación de excepción al recorrer la pila de llamadas.

  • En Linux con gcc, las funciones backtrace () y backtrace_symbols () pueden obtener información sobre la pila de llamadas actual. Vea la documentación de gcc cómo usarlos. El código debe compilarse con -g, de modo que los símbolos de depuración se coloquen en el ejecutable.

  • En Windows, puede recorrer la pila utilizando la biblioteca dbghelp y su función StackWalk64. Ver el article Jochen Kalmbach sobre CodeProject para más detalles. Esto funciona en depuración y liberación, y debe enviar archivos .pdb para todos los módulos sobre los que desee información.

Incluso puede combinar las dos soluciones recopilando información de la pila de llamadas cuando se lanza una excepción personalizada. La pila de llamadas se puede almacenar en la excepción, al igual que en .NET o Java. Tenga en cuenta que la recopilación de la pila de llamadas en Win32 es muy lenta (mi última prueba mostró aproximadamente 6 pilas de llamadas recopiladas por segundo). Si su código arroja muchas excepciones, este enfoque ralentiza considerablemente su programa.


La solución más simple es usar una macro:

#define throw_line(msg) / throw std::exception(msg " " __FILE__ ":" __LINE__) void f() { throw_line("Oh no!"); }


Parece que todos intentan mejorar tu código para generar excepciones en tu código, y nadie está intentando la pregunta real que hiciste.

Lo cual es porque no se puede hacer. Si el código que arroja la excepción solo se presenta en forma binaria (por ejemplo, en un archivo LIB o DLL), entonces el número de línea ha desaparecido, y no hay forma de conectar el objeto a una línea en el código fuente.


Si tiene una compilación de depuración y la ejecuta en el depurador de Visual Studio, puede entrar en el depurador cuando se produce cualquier tipo de excepción, antes de que se propague al mundo.

Habilítelo con la opción del menú Depurar> Excepciones y luego marque los tipos de excepciones que le interesan.

También puede agregar la capacidad de crear un archivo de volcado, si el código fuente de la aplicación es suyo. Con el archivo de volcado y los archivos PDB (símbolos) para la construcción específica, obtendrá stacktraces con WinDbg, por ejemplo.


Una mejor solución es usar una clase personalizada y una macro. :-)

#include <iostream> #include <sstream> #include <stdexcept> #include <string> class my_exception : public std::runtime_error { std::string msg; public: my_exception(const std::string &arg, const char *file, int line) : std::runtime_error(arg) { std::ostringstream o; o << file << ":" << line << ": " << arg; msg = o.str(); } ~my_exception() throw() {} const char *what() const throw() { return msg.c_str(); } }; #define throw_line(arg) throw my_exception(arg, __FILE__, __LINE__); void f() { throw_line("Oh no!"); } int main() { try { f(); } catch (const std::runtime_error &ex) { std::cout << ex.what() << std::endl; } }