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

  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. SMU Spring 2023 Trial Contest Round 9

    A. Wrong Subtraction  在k次操作里, 将n的最后一位数减1,如果是0就去掉,模拟一下就好了. #include <bits/stdc++.h> //#define i ...

  2. 【SpringCloud学习笔记(二)】用nacos做配置中心

    1. 学习目的 nacos除了作为服务注册中心之外,还能用作配置中心,可以说满足了日常的大部分需要.本次就是要学会如何使用nacos作为配置中心. 2. 操作 要使用nacos作为配置中心,需要首先引 ...

  3. 【CMake系列】08-debug release特性设置

    在构建的程序版本中,一共有 debug release minisize relwithDebugInfo四种,其中我们主要使用到就是 debug release 两种,这两种存在着一定的不同,deb ...

  4. SQL 求中位值

    题目A median is defined as a number separating the higher half of a data set from the lower half. Quer ...

  5. Java是值传递还是引用传递,又是怎么体现的

    关于Java是值传递还是引用传递,可以从代码层面来实现一下拿到结果 执行下面的代码: public static void main(String[] args) { int num = 10; St ...

  6. wxpython开发gui界面基础

    wxpython 开发gui 基础知识 一 .前言 记录使用wxpython开发gui工具吧.gui界面主要就是先布局,每个模块都是一个对象. 二.基础知识 import wx class MyFra ...

  7. 使用vue-cli4快速搭建项目环境、使用webpack4打包自己的library类库、封装vue插件并发布

    快速创建 使用官方推荐的vue-cli创建项目如下: # 安装 Vue Cli npm install -g @vue/cli # 创建一个项目 vue create vanttest # 创建完成后 ...

  8. 15. 三数之和 Golang实现

    给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j.i != k 且 j != k ,同时还满足 nums[i] + nums ...

  9. CSS & JS Effect – Dialog Modal

    效果 参考: Youtube – Create a Simple Popup Modal Youtube – Create a Modal (Popup) with HTML/CSS and Java ...

  10. HTML – script async defer

    参考 Youtube – #3 JavaScript Loading Strategies (async and defer) | JavaScript Full Tutorial no async ...