MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Как напечатать стек вызовов в обработчике исключения?"
Answer 809888
Стек вызовов проще всего вывести из SEH-фильтра, передавая в функцию StackWalk64 указатель на контекст, возвращенный GetExceptionInformation. Как-то так:
#include <stdlib.h> #include <locale.h> #include <stdio.h> #include <Windows.h> #include "DbgHelp.h" #pragma comment(lib, "Dbghelp.lib") const int MaxNameLen = 256; //выводит стек вызовов, соответствующий указанному контексту void printStack( CONTEXT* ctx ) { BOOL result; HANDLE process; HANDLE thread; HMODULE hModule; STACKFRAME64 stack; ULONG frame; DWORD64 displacement; char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; char name[ MaxNameLen ]; char module[MaxNameLen]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; // StackWalk64 модифицирует контекст в 64-битных приложениях, // что может привести к падению. Для предотвращения этого // создадим копию контекста. CONTEXT ctxCopy; memcpy(&ctxCopy, ctx, sizeof(CONTEXT)); memset( &stack, 0, sizeof( STACKFRAME64 ) ); process = GetCurrentProcess(); thread = GetCurrentThread(); displacement = 0; #if !defined(_M_AMD64) stack.AddrPC.Offset = (*ctx).Eip; stack.AddrPC.Mode = AddrModeFlat; stack.AddrStack.Offset = (*ctx).Esp; stack.AddrStack.Mode = AddrModeFlat; stack.AddrFrame.Offset = (*ctx).Ebp; stack.AddrFrame.Mode = AddrModeFlat; #endif SymInitialize( process, NULL, TRUE ); //загружаем символы for( frame = 0; ; frame++ ) { //получаем следующий вызов из стека result = StackWalk64 ( #if defined(_M_AMD64) IMAGE_FILE_MACHINE_AMD64 #else IMAGE_FILE_MACHINE_I386 #endif , process, thread, &stack, &ctxCopy, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL ); if( !result ) break; //полчаем имя символа для адреса pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; SymFromAddr(process, ( ULONG64 )stack.AddrPC.Offset, &displacement, pSymbol); hModule = NULL; lstrcpyA(module,""); GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCTSTR)(stack.AddrPC.Offset), &hModule); //получаем имя модуля if(hModule != NULL)GetModuleFileNameA(hModule,module,MaxNameLen); printf ("%lu: %s (in %s)\n",frame,pSymbol->Name,module); } } void BuggedFunction() { int * p = NULL; *p = 5; } void bar() { BuggedFunction(); } void foo() { bar(); } int seh_filter(_EXCEPTION_POINTERS* ex) { printf("Exception 0x%x occured\n",ex->ExceptionRecord->ExceptionCode); printStack(ex->ContextRecord); return EXCEPTION_EXECUTE_HANDLER; } int main(void) { setlocale(LC_ALL,"Russian"); __try { foo(); } __except(seh_filter(GetExceptionInformation())) { printf("Exception \n"); } getchar(); return 0; }
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.