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);
}
내 문제는, 그들이 최적화되지 않은 빌드에서 작동하지만, 에 대한 완전한 최적화가 아닙니다. 무슨 일이 일어나는가 나는 깨진 엔트리 하나를 얻은 다음 루프를 빠져 나가는 것이다. 디버그에서 전체 호출 스택을 얻었고 나중에 심볼을 찾을 때 모두 정확합니다.
디버거가 항상 수행 할 때 모든 빌드에서이 작업을 수행하는 것이 얼마나 어려울 지 이해할 수 없습니다. 나는 특별히 프레임 포인터가 코드 생성에서 생략되지 않는다고 말할 수있다. 먼저 디버그 용으로 빌드 한 다음 최적화를 none에서 전체 최적화로 변경하고 호출 스택 오류를 재현하기 위해 다시 작성합니다.
해결책에 대한 모든 힌트를 크게 주시면 감사하겠습니다.
/조나스
프레임 포인터 최적화 기능을 켜고 컴파일하지 않습니까? –
프레임 포인터가 코드 생성에서 생략되지 않는다. –