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

  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. redis集群主从之读写分离

    redis集群主从之读写分离 1.集群部署 这里就不详细赘述如何部署主从集群了,一般都是使用slaveOf配置来进行初始化配置. 2.与springboot集成实现读写分离 通过注解实现调用层读写分离 ...

  2. [nRF24L01+] 1. 硬件设计

    nRF24L01pluss_REFERENCE_MODULES.pdf nrf24l01p_product_specification_1_0.pdf 1. 硬件设计 1.1. 实物图 [左边是PCB ...

  3. Vue使用v-for 循环生成tabs 标签页

    实现最终效果: template代码: activeName:默认第一个显示的tab <el-tabs v-model="activeName" type="car ...

  4. AutoMaper使用

    使用 AutoMapper 进行赋值 一. 什么是 AutoMapper AutoMapper是对象到对象的映射工具.在完成映射规则之后,AutoMapper可以将源对象转换为目标对象. 二. Aut ...

  5. Java元注解介绍

    Java四种元注解相关介绍 概述 注解从Java1.5引入以来,不断地简化我们编写代码的流程,逐渐的也成为了我们必学的一项技术.我们学习了各种注解,学习了他们的用法,学习了他们的限制,是否想过他们的组 ...

  6. 移除 Parallels Access Sound 虚拟设备

    在安装了 Parallels 之后,发现 Mac 没声音,打开声音设置一看音频输出设备被设为了 Parallels Access Sound.把输出设备调回 MacBook 扬声器就有声音了. 但是音 ...

  7. c程序设计语言 by K&R(三)结构

    一.类型定义 typedef typedef int Length; typedef char* String; typedef struct tnode* Treeptr; typedef int ...

  8. svg之viewbox缩放

    先看个示例 代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> & ...

  9. webpack笔记-webpack基础用法(二)

    webpack 本质上是一个打包工具,它会根据代码的内容解析模块依赖,帮助我们把多个模块的代码打包. 一切文件:JavaScript.CSS.SCSS.图片.模板,在 Webpack 眼中都是一个个模 ...

  10. 终于有人把Modbus讲明白了

    大家好!我是付工. 2012年开始接触Modbus协议,至今已经有10多年了,从开始的懵懂,到后来的顿悟,再到现在的开悟,它始终岿然不动,变化的是我对它的认知和理解. 今天跟大家聊聊关于Modbus协 ...