利用DbgHelp获取线程的栈回溯信息
当线程发生异常时,我们如果可以记录下来异常线程的堆栈信息,那么对于我们后续问题处理将会有极大的帮助。这里记录一个操作方法。
1 #include <iostream> 2 #include <Windows.h> 3 #include <process.h> 4 #include <DbgHelp.h> 5 6 #pragma comment(lib, "Dbghelp.lib") 7 8 using std::cout; 9 using std::endl; 10 11 HANDLE g_hThread = INVALID_HANDLE_VALUE; 12 13 void StackTrack() 14 { 15 HANDLE hCurProcess = GetCurrentProcess(); 16 if(FALSE == SymInitialize(hCurProcess, NULL, TRUE)) 17 { 18 cout << "SymInitialize fail. LastError: 0x" << std::hex << GetLastError(); 19 return; 20 } 21 22 if (0xFFFFFFFF == SuspendThread(g_hThread)) 23 { 24 cout << "SuspendThread fail. LastError: 0x" << std::hex << GetLastError(); 25 return; 26 } 27 28 CONTEXT context; 29 context.ContextFlags = CONTEXT_FULL; 30 if (FALSE == GetThreadContext(g_hThread, &context)) 31 { 32 cout << "GetThreadContext fail. LastError: 0x" << std::hex << GetLastError(); 33 return; 34 } 35 36 DWORD machineType = IMAGE_FILE_MACHINE_I386; // 机器Cpu类型 37 38 STACKFRAME stackFrame = { 0 }; 39 #ifdef _M_IX86 40 machineType = IMAGE_FILE_MACHINE_I386; 41 stackFrame.AddrPC.Offset = context.Eip; 42 stackFrame.AddrPC.Mode = AddrModeFlat; 43 stackFrame.AddrStack.Offset = context.Esp; 44 stackFrame.AddrStack.Mode = AddrModeFlat; 45 stackFrame.AddrFrame.Offset = context.Ebp; 46 stackFrame.AddrFrame.Mode = AddrModeFlat; 47 #elif _M_X64 48 machineType = IMAGE_FILE_MACHINE_AMD64; 49 stackFrame.AddrPC.Offset = context->Rip; 50 stackFrame.AddrPC.Mode = AddrModeFlat; 51 stackFrame.AddrStack.Offset = context->Rsp; 52 stackFrame.AddrStack.Mode = AddrModeFlat; 53 stackFrame.AddrFrame.Offset = context->Rsp; 54 stackFrame.AddrFrame.Mode = AddrModeFlat; 55 #elif _M_IA64 56 machineType = IMAGE_FILE_MACHINE_IA64; 57 stackFrame.AddrPC.Offset = context->StIIP; 58 stackFrame.AddrPC.Mode = AddrModeFlat; 59 stackFrame.AddrStack.Offset = context->IntSp; 60 stackFrame.AddrStack.Mode = AddrModeFlat; 61 stackFrame.AddrFrame.Offset = context->IntSp; 62 stackFrame.AddrFrame.Mode = AddrModeFlat; 63 stackFrame.AddrBStore.Offset = context->RsBSP; 64 stackFrame.AddrBStore.Mode = AddrModeFlat; 65 #else 66 #error "platform not supported!" 67 #endif 68 69 typedef struct tag_SYMBOL_INFO 70 { 71 IMAGEHLP_SYMBOL symInfo; 72 TCHAR szBuffer[MAX_PATH]; 73 } SYMBOL_INFO, * LPSYMBOL_INFO; 74 75 decltype(stackFrame.AddrPC.Offset) dwDisplament = 0; 76 DWORD dwDis32 = 0; 77 SYMBOL_INFO stack_info = { 0 }; 78 PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&stack_info; 79 pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); 80 pSym->MaxNameLength = sizeof(SYMBOL_INFO) - offsetof(SYMBOL_INFO, symInfo.Name); 81 IMAGEHLP_LINE ImageLine = { 0 }; 82 ImageLine.SizeOfStruct = sizeof(IMAGEHLP_LINE); 83 84 while (TRUE == StackWalk( 85 machineType, 86 hCurProcess, 87 g_hThread, 88 &stackFrame, 89 &context, 90 NULL, 91 SymFunctionTableAccess, 92 SymGetModuleBase, 93 NULL) 94 ) 95 { 96 if (FALSE == SymGetSymFromAddr(hCurProcess, stackFrame.AddrPC.Offset, &dwDisplament, pSym)) 97 { 98 cout << "SymGetSymFromAddr fail. LastError: 0x" << std::hex << GetLastError(); 99 //continue; 100 } 101 if (FALSE == SymGetLineFromAddr(hCurProcess, stackFrame.AddrPC.Offset, &dwDis32, &ImageLine)) 102 { 103 cout << "SymGetLineFromAddr fail. LastError: 0x" << std::hex << GetLastError(); 104 //continue; 105 } 106 107 printf("当前调用函数 :(FILE[%s]LINE[%d]) %08x + %s \n", 108 ImageLine.FileName, ImageLine.LineNumber, pSym->Address, pSym->Name); 109 } 110 111 if (0xFFFFFFFF == ResumeThread(g_hThread)) 112 { 113 cout << "ResumeThread fail. LastError: 0x" << std::hex << GetLastError(); 114 return; 115 } 116 117 if (FALSE == SymCleanup(hCurProcess)) 118 { 119 cout << "SymCleanup fail. LastError: 0x" << std::hex << GetLastError(); 120 } 121 122 return; 123 } 124 125 126 void func1() 127 { 128 Sleep(10 * 1000); 129 } 130 131 void func2() 132 { 133 func1(); 134 } 135 136 void func3() 137 { 138 func2(); 139 } 140 141 unsigned _stdcall ThreadTestStack(void* lpArgList) 142 { 143 func3(); 144 return 0; 145 } 146 147 int main(int argc, char* argv[]) 148 { 149 unsigned uThreadID = 0; 150 g_hThread = (HANDLE)_beginthreadex(NULL, 0, &ThreadTestStack, NULL, 0, &uThreadID); 151 if (INVALID_HANDLE_VALUE == g_hThread) 152 { 153 cout << "_beginthreadex fail." << endl; 154 return 0; 155 } 156 157 Sleep(1 * 1000); 158 159 StackTrack(); 160 161 return 0; 162 }
本文来自博客园,作者:Arthurian,转载请注明原文链接:https://www.cnblogs.com/Arthurian/p/15722991.html
欢迎邮件交流:zhuanxinxin@aliyun.com