Проблемы с получением стека вызовов в сборке выпуска

Я изо всех сил пытался получить стек вызовов в исполняемом файле Windows. Я пробовал несколько разных способов получить стек вызовов. Ниже приведены некоторые примеры. Обратите внимание, что я немного изменил их и удалил обработку ошибок, чтобы облегчить их понимание, чтобы они не компилировались как есть. Я думаю, вы поняли.

Простой способ:

const int max_entries = 10;
void *entries[max_entries];
return CaptureStackBackTrace(0, max_entries, entries, 0);

Низкоуровневый способ:

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];
}

Совместимый способ:

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);
}

Моя проблема в том, что они работают в неоптимизированной сборке, но не при полной оптимизации. Что происходит, так это то, что я получаю один неработающий вход, а затем они выходят из своего цикла. При отладке я получаю полный стек вызовов, и когда я позже смотрю символы, все правильно.

Я не понимаю, как может быть сложно заставить эту работу во всех сборках, когда отладчик делает это все время . Могу конкретно сказать, что указатели кадров не опускаются при генерации кода. Сначала я создаю для отладки, а затем только меняю оптимизацию с нулевой на полную и перестраиваю, чтобы воспроизвести сбой стека вызовов.

Мы будем очень благодарны за любые подсказки решения.

/ Jonas

6
задан Jonas Hultén 14 February 2011 в 14:40
поделиться