He estado luchando por obtener una pila de llamadas en un ejecutable de Windows. He intentado varias formas diferentes de obtener la pila de llamadas. Los siguientes son algunos ejemplos. Tenga en cuenta que los modifiqué ligeramente y eliminé el manejo de errores para que sean fáciles de entender, por lo que es posible que no compilen como están. Creo que entiendes el punto.Problemas al obtener una pila de llamadas en una compilación de lanzamiento
La forma más sencilla:
const int max_entries = 10;
void *entries[max_entries];
return CaptureStackBackTrace(0, max_entries, entries, 0);
La manera de bajo nivel:
const int max_entries = 10;
void *entries[max_entries];
void **frame = 0;
__asm { mov frame, ebp }
unsigned int i = 0;
while(frame && i < max_entries) {
entries[i++] = frame[1];
frame = (void **)frame[0];
}
La manera compatible:
void *entries[max_entries];
CONTEXT context;
RtlCaptureContext(&context);
STACKFRAME64 stack_frame;
ZeroMemory(&stack_frame, sizeof(STACKFRAME64));
stack_frame.AddrPC.Offset = context.Eip;
stack_frame.AddrPC.Mode = AddrModeFlat;
stack_frame.AddrFrame.Offset = context.Ebp;
stack_frame.AddrFrame.Mode = AddrModeFlat;
stack_frame.AddrStack.Offset = context.Esp;
stack_frame.AddrStack.Mode = AddrModeFlat;
unsigned int num_frames = 0;
while (true) {
if (!StackWalk64(IMAGE_FILE_MACHINE_I386, GetCurrentProcess(),
GetCurrentThread(), &stack_frame, &context, NULL,
SymFunctionTableAccess64, SymGetModuleBase64, NULL))
break;
if (stack_frame.AddrPC.Offset == 0)
break;
entries[num_frames++] = reinterpret_cast<void *>(stack_frame.AddrPC.Offset);
}
Mi problema es que trabajan en una acumulación sin optimizar, pero no con optimización completa en. Lo que sucede es que obtengo una entrada rota y luego salen de sus bucles. En la depuración obtengo la pila de llamadas completa y cuando más tarde busco los símbolos, todo es correcto.
No entiendo cómo puede ser difícil hacer que esto funcione en todas las compilaciones cuando el depurador lo hace todo el tiempo. Puedo decir específicamente que los punteros de cuadro no se omiten en la generación de código. Primero compilo para la depuración y luego solo cambio la optimización de none a full optimization y recompé para reproducir la falla de la pila de llamadas.
Cualquier sugerencia para una solución será muy apreciada.
/Jonas
No está compilando con la optimización del puntero de marco activada, ¿verdad? –
Los punteros de cuadro no se omiten en la generación de código, si eso es lo que quiere decir. –