2008-12-24 5 views
7

¿Cómo obtengo un seguimiento de pila de direcciones en Windows sin usar dbghelp.dll?¿Cómo obtengo un seguimiento de pila en Windows sin usar dbghelp.dll?

No necesito saber cuáles son los símbolos o nombres de funciones asociados con las direcciones, solo quiero la lista de direcciones, algo similar a backtrace of *nix systems.

Gracias!

+0

¿Por qué querría hacer esto sin DbgHelp.dll. DbgHelp.dll está integrado en Windows, desde Windows 2000. También consulte el Stakwalker de Jochen Kalmbach: http://www.codeproject.com/KB/threads/StackWalker.aspx – Cheeso

Respuesta

9

Echa un vistazo a la función CaptureStackBackTrace(), que se encuentra en Kernel32.dll. Esto debería hacer todo lo que necesites.

Captura una traza de pila hacia atrás subiendo la pila y registrando la información de cada cuadro.

USHORT WINAPI CaptureStackBackTrace(
    __in  ULONG FramesToSkip, 
    __in  ULONG FramesToCapture, 
    __out  PVOID *BackTrace, 
    __out_opt PULONG BackTraceHash 
); 
+1

Se ve bien. Pero estoy usando VS 2005, y CaptureStackBackTrace no RtlCaptureBackTrace no está definido en winbase.h. Intentaré manualmente incluir el prototipo de función para RtlCaptureBackTrace (...) y ver si eso me funciona. ¡Gracias! – Uhall

+0

¡Genial! He escrito el código de seguimiento de pila ateast 3 veces y no tenía idea de que esto existe. ¡Gracias! – shoosh

+0

@Uhall: puede intentar instalar un SDK de Windows más nuevo. El cliente mínimo admitido figura como Windows XP, aunque la página de MSDN enumera que estaba incluido en el SDK de Windows a partir de Windows Vista. –

2

Si quieres hacer esto extremadamente no portable, sólo puede leer el registro EBP y caminar por la pila usted mismo. Esto solo funcionará para la arquitectura x86, y también supone que el tiempo de ejecución de C que está utilizando inicializa EBP a 0 antes de llamar a la primera función.

uint32_t read_ebp(void) 
{ 
    uint32_t my_ebp; 
    __asm 
    { 
     mov ebp, my_ebp 
    } 

    return my_ebp; 
} 

void backtrace(void) 
{ 
    uint32_t ebp = read_ebp(); 

    printf("backtrace:\n"); 

    while(ebp != 0) 
    { 
     printf("0x%08x\n", ebp); 
     ebp = ((uint32_t *)ebp)[1]; 
    } 
} 
+0

Con compilaciones de lanzamiento, esto solo le dará los primeros cuadros. Para que esto realmente funcione confiablemente, debe configurar "Omitir indicadores de cuadro" = No. – shoosh

+0

el destino es lo primero, por lo que necesita mover my_ebp, ebp .. aparte de eso, es bastante genial –

1

variante anterior no funciona para mí (msvc 6), por lo que:

unsigned long prev; 
unsigned long addr; 
__asm { mov prev, ebp } 
while(addr!=0) { 
    addr = ((unsigned long *)prev)[1]; 
    printf("0x%08x\n", addr); 
    prev = ((unsigned long *)prev)[0]; 
} 
Adam, gracias por poner de relieve la forma!

Cuestiones relacionadas