una pilas pila invertir implementacion estatica eliminar elemento ejemplos con comparar como colas cola codigo arreglos c debugging cross-platform callstack stack-trace

pilas - ¿Cómo puede uno agarrar un rastro de pila en C?



pilas en java (11)

Deberías estar usando la biblioteca de desenrollado .

unw_cursor_t cursor; unw_context_t uc; unw_word_t ip, sp; unw_getcontext(&uc); unw_init_local(&cursor, &uc); unsigned long a[100]; int ctr = 0; while (unw_step(&cursor) > 0) { unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); if (ctr >= 10) break; a[ctr++] = ip; }

Su enfoque también funcionaría bien a menos que realice una llamada desde una biblioteca compartida.

Puede usar el comando addr2line en Linux para obtener la función fuente / número de línea de la PC correspondiente.

Sé que no hay una función C estándar para hacer esto. Me preguntaba ¿cuáles son las técnicas para esto en Windows y * nix? (Windows XP es mi sistema operativo más importante para hacer esto en este momento).


En los últimos años he estado usando la libbacktrace de Ian Lance Taylor. Es mucho más limpio que las funciones en la biblioteca GNU C que requieren exportar todos los símbolos. Proporciona más utilidad para la generación de backtraces que libunwind. Y por último pero no menos importante, no es derrotado por ASLR como lo son los enfoques que requieren herramientas externas como addr2line .

Libbacktrace fue inicialmente parte de la distribución de GCC, pero ahora está disponible por el autor como una biblioteca independiente bajo una licencia BSD:

https://github.com/ianlancetaylor/libbacktrace

En el momento de escribir, no usaría nada más a menos que necesite generar trazas inversas en una plataforma que no es compatible con libbacktrace.


Hay backtrace () y backtrace_symbols ():

Desde la página man:

#include <execinfo.h> #include <stdio.h> ... void* callstack[128]; int i, frames = backtrace(callstack, 128); char** strs = backtrace_symbols(callstack, frames); for (i = 0; i < frames; ++i) { printf("%s/n", strs[i]); } free(strs); ...

Una forma de usar esto de una manera más conveniente / OOP es guardar el resultado de backtrace_symbols () en un constructor de clase de excepción. Por lo tanto, cada vez que arrojas ese tipo de excepción, tienes el rastro de la pila. Luego, solo proporcione una función para imprimirlo. Por ejemplo:

class MyException : public std::exception { char ** strs; MyException( const std::string & message ) { int i, frames = backtrace(callstack, 128); strs = backtrace_symbols(callstack, frames); } void printStackTrace() { for (i = 0; i

...

try { throw MyException("Oops!"); } catch ( MyException e ) { e.printStackTrace(); }

Ta da!

Nota: habilitar indicadores de optimización puede hacer que el seguimiento de la pila resultante sea inexacto. Idealmente, uno usaría esta capacidad con indicadores de corrección de errores y marcadores de optimización desactivados.



No hay una plataforma independiente para hacerlo.

Lo más cercano que puede hacer es ejecutar el código sin optimizaciones. De esta forma, puede conectarse al proceso (utilizando el depurador visual de c ++ o GDB) y obtener un seguimiento de pila utilizable.


Para Windows, CaptureStackBackTrace() también es una opción, que requiere menos código de preparación en el extremo del usuario que StackWalk64() . (Además, para una situación similar que tuve, CaptureStackBackTrace() terminó trabajando mejor (de manera más confiable) que StackWalk64() .


Para Windows, compruebe la API StackWalk64 () (también en Windows de 32 bits). Para UNIX, debe usar la forma nativa del sistema operativo para hacerlo, o recurrir a la barra posterior de glibc (), si está disponible.

Sin embargo, tenga en cuenta que tomar una Stacktrace en código nativo rara vez es una buena idea, no porque no sea posible, sino porque usualmente tratamos de lograr algo incorrecto.

La mayoría de las veces, la gente trata de obtener una pila en, por ejemplo, una circunstancia excepcional, como cuando se detecta una excepción, falla una afirmación o, peor y más equivocado de todos, cuando se produce una "excepción" fatal o señal como una violación de segmentación

Teniendo en cuenta el último problema, la mayoría de las API requerirá que asigne memoria explícitamente o puede hacerlo internamente. Hacerlo en el frágil estado en el que se encuentra actualmente su programa puede empeorar las cosas. Por ejemplo, el informe de bloqueo (o coredump) no reflejará la causa real del problema, sino su intento fallido de manejarlo).

Supongo que estás tratando de lograr esa cosa de manejo de errores fatales, ya que la mayoría de la gente parece intentar eso cuando se trata de obtener una stack stack. Si es así, me basaría en el depurador (durante el desarrollo) y dejaría que el proceso coredump en producción (o mini-volcado en Windows). Junto con la administración correcta de símbolos, no debería tener problemas para calcular la instrucción causante post-mortem.


Puedes hacerlo caminando la pila hacia atrás. En realidad, sin embargo, con frecuencia es más fácil agregar un identificador a la pila de llamadas al comienzo de cada función y mostrarlo al final, y luego simplemente recorrer esa impresión de los contenidos. Es un poco un PITA, pero funciona bien y le ahorrará tiempo al final.



Solaris tiene el comando pstack , que también se copió en Linux.