老外写的StackWalk64的封装类StackWalker。继承其并且重载onOutput可以得到堆栈。
2014-04-10 00:20
134 查看
关键是RtlCaptureContext得到当前的context。
http://www.codeproject.com/Articles/11132/Walking-the-callstack
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
To walk the callstack there is a documented interface:
Starting with Win9x/W2K, this interface is in thedbghelp.dll library (on NT, it is in imagehlp.dll). But the function name (
has changed starting with W2K (before it was called
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).
The usage of the class is very simple. For example if you want to display the callstack of the current thread, just instantiate a
and call the
This produces the following output in the debugger-output window:
You can now double-click on a line and the IDE will automatically jump to the desired file/line.
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
You have two options to do this: only overwrite the
The first solution (
(which should be enough for most of the cases). To output also to the console, you need to do the following:
If you want detailed info about the callstack (like loaded-modules, addresses, errors, ...) you can overwrite the corresponding methods. The following methods are provided:
These methods are called during the generation of the callstack.
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:
To do the actual stack-walking you need to call the following functions:
With this
which does the stack-walking:
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 StackWalkobject
and call the
ShowCallstackmember:
#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::ShowCallstack d:\privat\Articles\stackwalker\main.cpp (4): Func5 d:\privat\Articles\stackwalker\main.cpp (5): Func4 d:\privat\Articles\stackwalker\main.cpp (6): Func3 d:\privat\Articles\stackwalker\main.cpp (7): Func2 d:\privat\Articles\stackwalker\main.cpp (8): Func1 d:\privat\Articles\stackwalker\main.cpp (13): main f:\vs70builds\3077\vc\crtbld\crt\src\crt0.c (259): mainCRTStartup 77E614C7 (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 StackWalkerclass.
You have two options to do this: only overwrite the
OnOutputmethod or overwrite each
OnXxx-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 StackWalkeryou 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
相关文章推荐
- [转] 抽象类可以实现接口,并且可以继承实体类
- C语言也可以“面向对象”—— C语言实现封装、继承和多态
- StackWalker 堆栈打印
- ScalarHandler: 将单个值封装、 例如select count(*),求内容的条数;KeyedHandler:将多条记录封装到一个Map集合的Map集合中。并且外面的Map集合是可以指定的
- Thread类的getAllStackTraces()方法获取虚拟机中所有线程的StackTraceElement对象,可以查看堆栈
- 抽象类可以实现接口,并且可以继承实体类
- 如何判断一个C++对象是否在堆栈上(通过VirtualQuery这个API来获取堆栈的起始地址,然后就可以得到答案了),附许多精彩评论
- javascript封装类的技巧:具有私有成员、私有方法、特权属性、特权方法、原型对象、静态成员,最重要的是不会失去封装的优点,并且不影响继承
- 匿名内部类到底可不可以继承类或实现接口? Interface A{ public void method(); } 这时你可以写一个如下的语句得到接口A的实现类的对象 A a=new
- 使用SendMessage方法对窗体上的控件进行截图,该方法的思想就是把控件的句柄拿到,对控件发送WM_PAINT消息,并且把希望得到图形对象的句柄当作wParam参数传过去,这样就可以在图形对象得到想要得图形。
- 封装一个cout方法,能实现如此调用:cout(a)(b)(c)(d)(e)… 并且返回的值为参数连剩的结果,即a*b*c*d*e*…。如cout(1)(3)(7) 得到21
- [转] 抽象类可以实现接口,并且可以继承实体类
- Exception C++中讨论的异常安全堆栈的,封装内存管理的版本,使用私有继承的方式复用
- 假设你有一个各位数字互不相同的四位数,把所有的数字从大到小排序后得到a,从小到大后得到b,然后用a-b替换原来这个数,并且继续操作。例如,从1234出发,依次可以得到4321-1234=3087、87
- 如果一个箱子里面有100个球,有两个玩家,1和2,他们都很聪明,可以随机从箱子里面拿出2或6个球,箱子是透明的并且箱子里面有多少个球他们也可以看得到 ,如果算最后一个球能被谁拿到,谁就是
- RT8003: 'text-align' 特性在 IE6 IE7 IE8(Q) 中可以影响块级元素的对齐方式,并且在所有浏览器的混杂模式中均不能被 TABLE 元素继承
- 面向对象的特性:封装继承多态
- Java程序设计7——面向对象三大特征:封装、继承、多态
- Tomcat 7.0.3x 启动慢并且遇到StackOverflowError的异常的解决办法
- 如果判断图片是否存在,可以使用javascript,省资源并且方便简单.