利用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 一段文本描述信息. 比如 ...
随机推荐
- 暑假Java自学进度总结06
一.今日所学: 1.for循环 for(初始化语句;条件判断语句;条件控制语句){ 循环体语句; } 执行流程: 1>执行初始化语句 2>执行条件判断语句,若为true则执行循环体语句,若 ...
- ARMv8-A 地址翻译技术之MMU的前世今生
MMU的重要性不言而喻,支撑操作系统之上的各种复杂应用.但在正式讲MMU之前,我们先说说MMU的发展史,因为ARMv8-A的MMU相当复杂,直接切入正题,会显得比较枯燥.废话不多说,咱们马上开始: 一 ...
- SPI转can芯片CSM300详解以及Linux驱动移植调试笔记
一.CSM300概述 CSM300(A)系列是一款可以支持 SPI / UART 接口的CAN模块. 1. 简介 CSM300(A)系列隔离 SPI / UART 转 CAN 模块是集成微处理器. C ...
- JavaScript设计模式样例五 —— 建造者模式
建造者模式(Builder Pattern) 定义:使用多个简单的对象一步一步构建成一个复杂的对象. 目的:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. 场景:一些基本部件不 ...
- 低版本安卓home assistant网页浏览器
试了很久 一直有问题的一点 , 使用普通浏览器加载不出来登录界面 只能加载出icon 然后就没反应了 考虑到了webview的问题 但是没想到安卓5.0之前是固定且不可升级的webview 从 And ...
- hacs安装
安装 HACS 直接使用 Docker 的可视化管理面板 Portainer 或者通过命令行进入 Docker 容器,然后执行以下安装命令: docker exec -it <容器名称或容器ID ...
- zblog免费插件分享前端代码支持一键复制
zblog默认的代码文件在网页前端是不支持一键复制的,这会让访客复制长代码的时候不太方便,甚至有可能会出错,影响体验,下面分享一个非常简单的免费插件,安装之后,前端代码就能一键复制了. 插件使用方法: ...
- Coursera, Big Data 5, Graph Analytics for Big Data, Week 4
Graph Analytics With Neo4j 讲了怎样用Cypher 脚本语言去操作 Neo4j, 包括加graph, 导入csv数据. 接着讲了一些neo4j 的基本操作. 最后讲的,pat ...
- [big data] main entry for Spark, Zeppelin, Delta Lake ...
1. 环境搭建 big data env setup 2. Spark 学习 spark 怎么读写 elasticsearch spark 怎么 连接 读写 ElasticSearch Spark 上 ...
- Falcon Mamba: 首个高效的无注意力机制 7B 模型
Falcon Mamba 是由阿布扎比的 Technology Innovation Institute (TII) 开发并基于 TII Falcon Mamba 7B License 1.0 的开放 ...