利用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 }
利用DbgHelp获取线程的栈回溯信息的更多相关文章
- linux内核中打印栈回溯信息 - dump_stack()函数分析【转】
转自:http://blog.csdn.net/jasonchen_gbd/article/details/45585133 版权声明:本文为博主原创文章,转载请附上原博链接. 目录(?)[-] ...
- 怎么从代码中拿到栈回溯信息(call stack trace)
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:怎么从代码中拿到栈回溯信息(call stack trace).
- 【转】StackTraceElement获取方法调用栈的信息
本文链接:https://blog.csdn.net/hp910315/article/details/52702199 一.什么是StackTrace StackTrace(堆栈轨迹)存放的就是方法 ...
- java 利用ManagementFactory获取jvm,os的一些信息--转
原文地址:http://blog.csdn.net/dream_broken/article/details/49759043 想了解下某个Java项目的运行时jvm的情况,可以使用一些监控工具,比如 ...
- 利用DNSLOG获取看不到的信息(给盲注带上眼镜)
一.前言 本文原创作者:sucppVK,本文属i春秋原创奖励计划,未经许可禁止转载! 毕业设计总算搞得差不多了,这个心累啊.这不,完成了学校的任务,赶紧回来给蛋总交作业.今天给大家分享一个姿势吧,不是 ...
- 编程实战——电影管理器之利用MediaInfo获取高清视频文件的相关信息
随着高速(20M)宽带.HTPC.大容量硬盘(3T)的普及,下载高清片并利用大屏幕观看也成为普通的事情. 随着下载影片的增多,管理就有了问题,有时在茫茫文件夹下找寻一个影片也是一件费时费力的事. 于是 ...
- java业务逻辑,利用hibernate获取所连接的数据库信息
1.本人程序架构是springMVC+hibernate,这次的需求是要针对不同的数据库,做不同的处理. 2.获取所连接的数据库是什么,oracle? mysql? sql server? 基础 ...
- linux中oops信息的调试及栈回溯【转】
本文转载自:http://blog.csdn.net/kangear/article/details/8217329 ========================================= ...
- Oops信息及栈回溯
1. Oops信息来源及格式Oops这个单词含义为“惊讶”,当内核出错时(比如访问非法地址)打印出来的信息被称为Oops信息.Oops信息包含以下几部分内容:(1)一段文本描述信息. 比如类 ...
- linux中Oops信息的调试及栈回溯
Oops 信息来源及格式 Oops 这个单词含义为“惊讶” ,当内核出错时(比如访问非法地址)打印出来的信息被 称为 Oops 信息. Oops 信息包含以下几部分内容. 1 一段文本描述信息. 比如 ...
随机推荐
- 关于Springboot理解
面向对象五大基本原则 graph LR A(面向对象五大原则);B(单一职责原则);C(开放封闭原则);D(里式替换原则);E(依赖倒置原则);F(接口隔离原则); A---B;A---C;A---D ...
- Oracle数据库自动备份
1.bat脚本 格式为ANSI格式 set CURDATE=%date:~0,4%%date:~5,2%%date:~8,2% set CURMON=%date:~0,4%%date:~5,2% se ...
- 使用命令行 Windows 修改文件权限
修改文件访问权限的命令行工具是 icacls,其使用语法是这样的: icacls <file> # 查看文件的访问权限 icacls <file> /grant <SID ...
- spark 中时间和日期 操作,怎么找到前几天后几天
1. timestamp 增加减少一个 time delta df.withColumn("added_hours",col("input_timestamp" ...
- in notin exists not exists 性能优化算法总结
in notin exists not exists 性能优化算法总结 1.1. in 和 exists 区别 1.2. not in 能不能走索引 1.3. not in 和 join 的关系 1. ...
- Dell存储备份告警:
创建时间 修改日期 对象名称 消息 类型 告警状态 已确认 告警定义 类型 23-3-12 11:59:26 23-3-12 11:59:37 copyMirrorswap 2 CMs Operati ...
- 微软RDL远程代码执行超高危漏洞(CVE-2024-38077)漏洞检测排查方式
漏洞名称:微软RDL远程代码执行超高危漏洞(CVE-2024-38077) CVSS core: 9.8 漏洞描述: CVE-2024-38077 是微软近期披露的一个极其严重的远程代码执行漏洞. ...
- 『面试题』WEB前端面试专题-Promise相关
题目一 const promise = new Promise((resolve, reject) => { console.log(1); resolve(); console.log(2); ...
- HTML – script async defer
参考 Youtube – #3 JavaScript Loading Strategies (async and defer) | JavaScript Full Tutorial no async ...
- manim边学边做--弧形多边形
弧形多边形是一种结合了圆弧和多边形的图形,这类几何图形在设计中应用非常广泛. 比如在家居设计中,看看家里的沙发,餐桌和座椅等,它们的边角,靠背等地方都是弧形的设计,这种设计有效柔化了室内空间,使整体氛 ...