reales - Rastreo de la pila de la pantalla C++ en la excepción
libro de android studio en español pdf (13)
Quiero tener una manera de informar el seguimiento de la pila al usuario si se produce una excepción. ¿Cuál es la mejor manera de hacer esto? ¿Se necesita una gran cantidad de código adicional?
Para responder preguntas:
Me gustaría que sea portátil si es posible. Quiero que aparezca la información, para que el usuario pueda copiar el seguimiento de la pila y enviarme un correo electrónico si aparece un error.
AFAIK libunwind es bastante portátil y hasta ahora no he encontrado nada más fácil de usar.
Cpp-tool ex_diag : uso sencillo, multiplataforma, uso mínimo de recursos, simple y flexible en el seguimiento.
Depende de qué plataforma.
En GCC es bastante trivial, mira esta publicación para más detalles.
En MSVC, puede usar la biblioteca StackWalker que maneja todas las llamadas API subyacentes necesarias para Windows.
Tendrá que descubrir la mejor manera de integrar esta funcionalidad en su aplicación, pero la cantidad de código que necesita para escribir debe ser mínima.
El siguiente código detiene la ejecución justo después de lanzar una excepción. Necesita establecer un manejador de excepción de Windows junto con un manejador de terminación. Probé esto en MinGW 32bits.
void beforeCrash(void);
static const bool SET_TERMINATE = std::set_terminate(beforeCrash);
void beforeCrash() {
__asm("int3");
}
int main(int argc, char *argv[])
{
SetUnhandledExceptionFilter(windows_exception_handler);
...
}
Compruebe el siguiente código para la función windows_exception_handler: http://www.codedisqus.com/0ziVPgVPUk/exception-handling-and-stacktrace-under-windows-mingwgcc.html
En Windows, echa un vistazo a BugTrap . Ya no está en el enlace original, pero aún está disponible en CodeProject.
La respuesta de Andrew Grant no ayuda a obtener un seguimiento de pila de la función de lanzamiento , al menos no con GCC, porque una instrucción throw no guarda el seguimiento de la pila actual por sí mismo, y el controlador catch no tendrá acceso al seguimiento de la pila en ese punto más.
La única manera, mediante GCC, de resolver esto es asegurarse de generar un seguimiento de pila en el punto de la instrucción throw y guardarlo con el objeto de excepción.
Este método requiere, por supuesto, que cada código que arroje una excepción use esa clase particular de Excepción.
Actualización 11 de julio de 2017 : para obtener algún código útil, eche un vistazo a la respuesta de cahit beyaz, que apunta a http://stacktrace.sourceforge.net/ . No la he usado todavía pero parece prometedora.
Me gustaría agregar una opción de biblioteca estándar (es decir, multiplataforma) cómo generar trazas inversas de excepción, que se ha vuelto disponible con C ++ 11 :
Use std::nested_exception
y std::throw_with_nested
Esto no te dará la posibilidad de relajarte, pero en mi opinión es la mejor opción. Se describe en here y here , cómo puede obtener un seguimiento de sus excepciones dentro de su código sin necesidad de un depurador o un registro engorroso, simplemente escribiendo un controlador de excepciones adecuado que volverá a generar excepciones anidadas.
¡Ya que puede hacer esto con cualquier clase de excepción derivada, puede agregar mucha información a tal retroceso! También puede echar un vistazo a mi MWE en GitHub , donde una traza inversa se vería así:
Library API: Exception caught in function ''api_function''
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
Recomiendo el proyecto http://stacktrace.sourceforge.net/ . Admite Windows, Mac OS y también Linux
Si está utilizando Boost 1.65 o superior, puede usar boost::stacktrace :
#include <boost/stacktrace.hpp>
// ... somewhere inside the bar(int) function that is called recursively:
std::cout << boost::stacktrace::stacktrace();
Tengo un problema similar, y aunque me gusta la portabilidad, solo necesito el soporte de gcc. En gcc, execinfo.h y las llamadas backtrace están disponibles. Para exigir los nombres de las funciones, el Sr. Bingmann tiene una buena pieza de código. Para volcar una traza inversa en una excepción, creo una excepción que imprime la traza inversa en el constructor. Si esperaba que esto funcionara con una excepción arrojada en una biblioteca, podría requerir una reconstrucción / vinculación para que se use la excepción de retroceso.
/******************************************
#Makefile with flags for printing backtrace with function names
# compile with symbols for backtrace
CXXFLAGS=-g
# add symbols to dynamic symbol table for backtrace
LDFLAGS=-rdynamic
turducken: turducken.cc
******************************************/
#include <cstdio>
#include <stdexcept>
#include <execinfo.h>
#include "stacktrace.h" /* https://panthema.net/2008/0901-stacktrace-demangled/ */
// simple exception that prints backtrace when constructed
class btoverflow_error: public std::overflow_error
{
public:
btoverflow_error( const std::string& arg ) :
std::overflow_error( arg )
{
print_stacktrace();
};
};
void chicken(void)
{
throw btoverflow_error( "too big" );
}
void duck(void)
{
chicken();
}
void turkey(void)
{
duck();
}
int main( int argc, char *argv[])
{
try
{
turkey();
}
catch( btoverflow_error e)
{
printf( "caught exception: %s/n", e.what() );
}
}
Al compilar y ejecutar esto con gcc 4.8.4, se obtiene una traza inversa con los nombres de funciones de C ++ muy bien definidos.
stack trace:
./turducken : btoverflow_error::btoverflow_error(std::string const&)+0x43
./turducken : chicken()+0x48
./turducken : duck()+0x9
./turducken : turkey()+0x9
./turducken : main()+0x15
/lib/x86_64-linux-gnu/libc.so.6 : __libc_start_main()+0xf5
./turducken() [0x401629]
en Linux con g ++ echa un vistazo a esta lib
https://sourceforge.net/projects/libcsdbg
Hace todo el trabajo por ti
Poppy puede recopilar no solo la traza de la pila, sino también los valores de los parámetros, las variables locales, etc., todo lo que conduce al bloqueo.