老外写的StackWalk64的封装类StackWalker。继承其并且重载onOutput可以得到堆栈。
来源:互联网 发布:交大知行大厦招聘 编辑:程序博客网 时间:2024/06/05 14:47
关键是RtlCaptureContext得到当前的context。
http://www.codeproject.com/Articles/11132/Walking-the-callstack
Introduction
In some cases you need to display the callstack of the current thread or your are just interested in the callstack of other threads / processes. Therefore I wrote this project.
The goal for this project was the following:
- Simple interface to generate a callstack
- C++ based to allow overwrites of several methods
- Hiding the implementation details (API) from the class' interface
- Support of x86, x64 and IA64 architecture
- Default output to debugger-output window (but can be customized)
- Support of user-provided read-memory-function
- Support of the widest range of development-IDEs (VC5-VC8)
- Most portable solution to walk the callstack
Background
To walk the callstack there is a documented interface: StackWalk64
. Starting with Win9x/W2K, this interface is in thedbghelp.dll library (on NT, it is in imagehlp.dll). But the function name (StackWalk64
) has changed starting with W2K (before it was called StackWalk
(without the 64
))! This project only supports the newer Xxx64-funtions. If you need to use it on older systems, you can download the redistributable for NT/W9x.
The latest dbghelp.dll can always be downloaded with the Debugging Tools for Windows. This also contains thesymsrv.dll which enables the use of the public Microsoft symbols-server (can be used to retrieve debugging information for system-files; see below).
Using the code
The usage of the class is very simple. For example if you want to display the callstack of the current thread, just instantiate a StackWalk
object and call the ShowCallstack
member:
#include <windows.h>#include "StackWalker.h"void Func5() { StackWalker sw; sw.ShowCallstack(); }void Func4() { Func5(); }void Func3() { Func4(); }void Func2() { Func3(); }void Func1() { Func2(); }int main(){ Func1(); return 0;}
This produces the following output in the debugger-output window:
[...] (output stripped)d:\privat\Articles\stackwalker\stackwalker.cpp (736): StackWalker::ShowCallstackd:\privat\Articles\stackwalker\main.cpp (4): Func5d:\privat\Articles\stackwalker\main.cpp (5): Func4d:\privat\Articles\stackwalker\main.cpp (6): Func3d:\privat\Articles\stackwalker\main.cpp (7): Func2d:\privat\Articles\stackwalker\main.cpp (8): Func1d:\privat\Articles\stackwalker\main.cpp (13): mainf:\vs70builds\3077\vc\crtbld\crt\src\crt0.c (259): mainCRTStartup77E614C7 (kernel32): (filename not available): _BaseProcessStart@4
You can now double-click on a line and the IDE will automatically jump to the desired file/line.
Providing own output-mechanism
If you want to direct the output to a file or want to use some other output-mechanism, you simply need to derive from the StackWalker
class. You have two options to do this: only overwrite the OnOutput
method or overwrite eachOnXxx
-function. The first solution (OnOutput
) is very easy and uses the default-implementation of the other OnXxx
-functions (which should be enough for most of the cases). To output also to the console, you need to do the following:
class MyStackWalker : public StackWalker{public: MyStackWalker() : StackWalker() {}protected: virtual void OnOutput(LPCSTR szText) { printf(szText); StackWalker::OnOutput(szText); }};
Retrieving detailed callstack info
If you want detailed info about the callstack (like loaded-modules, addresses, errors, ...) you can overwrite the corresponding methods. The following methods are provided:
class StackWalker{protected: virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName); virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion); virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry); virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr);};
These methods are called during the generation of the callstack.
Various kinds of callstacks
In the constructor of the class, you need to specify if you want to generate callstacks for the current process or for another process. The following constructors are available:
class StackWalker{public: StackWalker( int options = OptionsAll, LPCSTR szSymPath = NULL, DWORD dwProcessId = GetCurrentProcessId(), HANDLE hProcess = GetCurrentProcess() ); // Just for other processes with // default-values for options and symPath StackWalker( DWORD dwProcessId, HANDLE hProcess );};
To do the actual stack-walking you need to call the following functions:
class StackWalker{public: BOOL ShowCallstack( HANDLE hThread = GetCurrentThread(), CONTEXT *context = NULL, PReadProcessMemoryRoutine readMemoryFunction = NULL, LPVOID pUserData = NULL );};
Displaying the callstack of an exception
With this StackWalker
you can also display the callstack inside an exception handler. You only need to write a filter-function which does the stack-walking:
// The exception filter function:LONG WINAPI ExpFilter(EXCEPTION_POINTERS* pExp, DWORD dwExpCode){ StackWalker sw; sw.ShowCallstack(GetCurrentThread(), pExp->ContextRecord); return EXCEPTION_EXECUTE_HANDLER;}// This is how to catch an exception:__try{ // do some ugly stuff...}__except (ExpFilter(GetExceptionInformation(), GetExceptionCode())){}
Points of Interest
Context and callstack
- 老外写的StackWalk64的封装类StackWalker。继承其并且重载onOutput可以得到堆栈。
- 老外写的SQLite3封装类
- 老外写的coreimage
- 老外写的正则表达式的类
- 老外写的正则表达式的类
- 老外写的正则表达式的类
- 老外写的正则表达式的类
- 方法的继承,覆写和重载
- java反射得到类对象,并且得到类的属性
- 老外写的PHP的SMTP邮件类
- 老外写的一个类,数字转换成英文
- 老外写的winform打印类(很好用,已经测试)
- java的重写、重载以及继承、多态和封装
- 方法的重载与重写 区别 封装 继承 多态
- Java中面向对象的封装,继承,重载重写
- 类的继承与重载
- 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。 虽然使用其他方法也可以对外共享数
- 老外写的书看起来就是轻松 :-)
- 《Hadoop权威指南》- 1、初识Hadoop
- LeetCode || 总结(持续更新)
- 1
- git 配置与git 版本库
- jquery编写兼容IE6的返回顶部功能
- 老外写的StackWalk64的封装类StackWalker。继承其并且重载onOutput可以得到堆栈。
- 140 - Bandwidth 回溯
- 10603 - Fill uva 隐式图的遍历
- C&C++混合编程
- C++优先级列表
- Linux下的lds链接脚本基础
- MySQL:索引工作原理
- java压缩文件三
- UVA 11019 Matrix Matcher(AC自动机:矩阵匹配)