当线程发生异常时,我们如果可以记录下来异常线程的堆栈信息,那么对于我们后续问题处理将会有极大的帮助。这里记录一个操作方法。

  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 }

利用DbgHelp获取线程的栈回溯信息的更多相关文章

  1. linux内核中打印栈回溯信息 - dump_stack()函数分析【转】

    转自:http://blog.csdn.net/jasonchen_gbd/article/details/45585133 版权声明:本文为博主原创文章,转载请附上原博链接.   目录(?)[-] ...

  2. 怎么从代码中拿到栈回溯信息(call stack trace)

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:怎么从代码中拿到栈回溯信息(call stack trace).

  3. 【转】StackTraceElement获取方法调用栈的信息

    本文链接:https://blog.csdn.net/hp910315/article/details/52702199 一.什么是StackTrace StackTrace(堆栈轨迹)存放的就是方法 ...

  4. java 利用ManagementFactory获取jvm,os的一些信息--转

    原文地址:http://blog.csdn.net/dream_broken/article/details/49759043 想了解下某个Java项目的运行时jvm的情况,可以使用一些监控工具,比如 ...

  5. 利用DNSLOG获取看不到的信息(给盲注带上眼镜)

    一.前言 本文原创作者:sucppVK,本文属i春秋原创奖励计划,未经许可禁止转载! 毕业设计总算搞得差不多了,这个心累啊.这不,完成了学校的任务,赶紧回来给蛋总交作业.今天给大家分享一个姿势吧,不是 ...

  6. 编程实战——电影管理器之利用MediaInfo获取高清视频文件的相关信息

    随着高速(20M)宽带.HTPC.大容量硬盘(3T)的普及,下载高清片并利用大屏幕观看也成为普通的事情. 随着下载影片的增多,管理就有了问题,有时在茫茫文件夹下找寻一个影片也是一件费时费力的事. 于是 ...

  7. java业务逻辑,利用hibernate获取所连接的数据库信息

    1.本人程序架构是springMVC+hibernate,这次的需求是要针对不同的数据库,做不同的处理. 2.获取所连接的数据库是什么,oracle?  mysql?  sql server?  基础 ...

  8. linux中oops信息的调试及栈回溯【转】

    本文转载自:http://blog.csdn.net/kangear/article/details/8217329 ========================================= ...

  9. Oops信息及栈回溯

    1. Oops信息来源及格式Oops这个单词含义为“惊讶”,当内核出错时(比如访问非法地址)打印出来的信息被称为Oops信息.Oops信息包含以下几部分内容:(1)一段文本描述信息.      比如类 ...

  10. linux中Oops信息的调试及栈回溯

    Oops 信息来源及格式 Oops 这个单词含义为“惊讶” ,当内核出错时(比如访问非法地址)打印出来的信息被 称为 Oops 信息. Oops 信息包含以下几部分内容. 1 一段文本描述信息. 比如 ...

随机推荐

  1. CH02_数据类型

    CH02_数据类型 数据类型 整型 描述:整型变量表示的是整型类型的数据,C++中能够表示整型的类型有以下几种方式,区别在于所占内存空间不同. 数据类型 占用空间 取值范围 short(短整型) 2字 ...

  2. fs4412 I2C驱动基于Cortex-A9,mpu6050裸机程序,驱动,I2C架构,有这一篇够了

    本文基于三星Cortex-A9架构,Exynos4412讲解I2C原理.以及基于I2C的mpu6050陀螺仪的数据读取实例(包括在裸机模式下数据的读取以及基于Linux驱动的读取).还会分析Linux ...

  3. esp32挂esphome

    esp32挂esphome 使用docker创建容器 docker run -d --name='esphome' \ --restart=always \ -p 6052:6052 \ -e TZ= ...

  4. 【Jmeter】之进行单接口批量压力测试

    目录: 一.安装Jmeter 二.接口压力测试 p.p1 { margin: 0; font: 14px ".PingFang SC"; color: rgba(17, 31, 4 ...

  5. 😶‍🌫️ SpringBoot中MongoDB的骚操作用法

    不知道大家在工作项目中有没有使用MongoDB,在哪些场景中使用.MongoDB作为NoSQL数据库,不像SQL数据库那样,可以使用Mybatis框架. 如果需要在SpringBoot中使用Mongo ...

  6. 光影精灵10 Win1+Ubuntu18.04 双系统 踩坑记录

    前言 第二年准备报名智能车了,当然还是创意组别.刚好买了今年新出的电脑光影精灵10,我想着也给它安一个双系统.但是没想到,相比于之前那个老电脑,新电脑的新硬件和驱动问题远比老电脑麻烦的多. 在经历了一 ...

  7. Amaze UI框架的图标

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  8. 【转】一种Vue应用程序错误/异常处理机制

    在前端应用程序中,最常见的错误/异常类型可能包括以下几种: 语法错误:使用了一些错误的语法 运行时错误:由于执行期间的非法操作导致的 逻辑错误:由于程序逻辑错误 Http 错误:API 返回的错误 有 ...

  9. Angular Material 18+ 高级教程 – CDK Overlay

    Overlay, Dialog, Modal, Popover 傻傻分不清楚 参考: Medium – Modal?Dialog?你真的知道他們是什麼嗎? Popups, dialogs, toolt ...

  10. 全面掌握 Jest:从零开始的测试指南(上篇)

    随着JavaScript在前后端开发中的广泛应用,测试已成为保证代码质量的关键环节. 为什么需要单元测试 在我们的开发过程中,经常需要定义一些算法函数,例如将接口返回的数据转换成UI组件所需的格式.为 ...