23 #if defined(WIN32) && defined(CRASH_HANDLER)
35 #pragma warning (push)
36 #pragma warning (disable:4091) // warning C4091: 'typedef ': ignored on left of '' when no variable is declared
46 const char *getExceptionName(DWORD exceptionCode)
48 switch (exceptionCode) {
49 case EXCEPTION_ACCESS_VIOLATION:
return "Access violation";
50 case EXCEPTION_DATATYPE_MISALIGNMENT:
return "Datatype misalignment";
51 case EXCEPTION_BREAKPOINT:
return "Breakpoint";
52 case EXCEPTION_SINGLE_STEP:
return "Single step";
53 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
return "Array bounds exceeded";
54 case EXCEPTION_FLT_DENORMAL_OPERAND:
return "Float denormal operand";
55 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
return "Float divide by zero";
56 case EXCEPTION_FLT_INEXACT_RESULT:
return "Float inexact result";
57 case EXCEPTION_FLT_INVALID_OPERATION:
return "Float invalid operation";
58 case EXCEPTION_FLT_OVERFLOW:
return "Float overflow";
59 case EXCEPTION_FLT_STACK_CHECK:
return "Float stack check";
60 case EXCEPTION_FLT_UNDERFLOW:
return "Float underflow";
61 case EXCEPTION_INT_DIVIDE_BY_ZERO:
return "Integer divide by zero";
62 case EXCEPTION_INT_OVERFLOW:
return "Integer overflow";
63 case EXCEPTION_PRIV_INSTRUCTION:
return "Privileged instruction";
64 case EXCEPTION_IN_PAGE_ERROR:
return "In page error";
65 case EXCEPTION_ILLEGAL_INSTRUCTION:
return "Illegal instruction";
66 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
return "Noncontinuable exception";
67 case EXCEPTION_STACK_OVERFLOW:
return "Stack overflow";
68 case EXCEPTION_INVALID_DISPOSITION:
return "Invalid disposition";
69 case EXCEPTION_GUARD_PAGE:
return "Guard page";
70 case EXCEPTION_INVALID_HANDLE:
return "Invalid handle";
72 return "Unknown exception";
75 void Stacktrace(LPEXCEPTION_POINTERS e, std::stringstream& ss)
77 PIMAGEHLP_SYMBOL pSym;
79 HANDLE process, thread;
80 ULONG_PTR dwModBase, Disp;
84 char modname[MAX_PATH];
85 char symBuffer[
sizeof(IMAGEHLP_SYMBOL) + 255];
87 pSym = (PIMAGEHLP_SYMBOL)symBuffer;
89 ZeroMemory(&sf,
sizeof(sf));
91 sf.AddrPC.Offset = e->ContextRecord->Rip;
92 sf.AddrStack.Offset = e->ContextRecord->Rsp;
93 sf.AddrFrame.Offset = e->ContextRecord->Rbp;
94 machineType = IMAGE_FILE_MACHINE_AMD64;
96 sf.AddrPC.Offset = e->ContextRecord->Eip;
97 sf.AddrStack.Offset = e->ContextRecord->Esp;
98 sf.AddrFrame.Offset = e->ContextRecord->Ebp;
99 machineType = IMAGE_FILE_MACHINE_I386;
102 sf.AddrPC.Mode = AddrModeFlat;
103 sf.AddrStack.Mode = AddrModeFlat;
104 sf.AddrFrame.Mode = AddrModeFlat;
106 process = GetCurrentProcess();
107 thread = GetCurrentThread();
110 more = StackWalk(machineType, process, thread, &sf, e->ContextRecord, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL);
111 if(!more || sf.AddrFrame.Offset == 0)
114 dwModBase = SymGetModuleBase(process, sf.AddrPC.Offset);
116 GetModuleFileName((HINSTANCE)dwModBase, modname, MAX_PATH);
118 strcpy(modname,
"Unknown");
121 pSym->SizeOfStruct =
sizeof(symBuffer);
122 pSym->MaxNameLength = 254;
124 if(SymGetSymFromAddr(process, sf.AddrPC.Offset, &Disp, pSym))
125 ss <<
stdext::format(
" %d: %s(%s+%#0lx) [0x%016lX]\n", count, modname, pSym->Name, Disp, sf.AddrPC.Offset);
127 ss <<
stdext::format(
" %d: %s [0x%016lX]\n", count, modname, sf.AddrPC.Offset);
133 LONG CALLBACK ExceptionHandler(LPEXCEPTION_POINTERS e)
136 SymInitialize(GetCurrentProcess(), 0, TRUE);
137 std::stringstream ss;
138 ss <<
"== application crashed\n";
146 ss <<
stdext::format(
"exception: %s (0x%08lx)\n", getExceptionName(e->ExceptionRecord->ExceptionCode), e->ExceptionRecord->ExceptionCode);
147 ss <<
stdext::format(
"exception address: 0x%08lx\n", (
size_t)e->ExceptionRecord->ExceptionAddress);
151 SymCleanup(GetCurrentProcess());
158 GetCurrentDirectory(
sizeof(dir) - 1, dir);
159 std::string fileName =
stdext::format(
"%s\\crashreport.log", dir);
160 std::ofstream fout(fileName.c_str(), std::ios::out | std::ios::app);
161 if(fout.is_open() && fout.good()) {
170 "The application has crashed.\n\n"
171 "A crash report has been written to:\n"
172 "%s", fileName.c_str());
173 MessageBox(NULL, msg.c_str(),
"Application crashed", 0);
179 return EXCEPTION_CONTINUE_SEARCH;
182 void installCrashHandler()
184 SetUnhandledExceptionFilter(ExceptionHandler);