Chinaunix首页 | 论坛 | 博客
  • 博客访问: 348917
  • 博文数量: 88
  • 博客积分: 1695
  • 博客等级: 上尉
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-06 15:48
个人简介

喜欢美食, 旅行..

文章分类

全部博文(88)

文章存档

2014年(2)

2013年(12)

2012年(14)

2010年(8)

2009年(52)

我的朋友

分类: WINDOWS

2012-12-05 22:25:47

1. 获得当前的调用堆栈. < 请参考下面的函数实现 _printCallStark >
在当前线程去获得自己的调用堆栈, 我的做法是借助异常机制, 获得当前线程的下上文.然后通过 API 函数 StackWalk 遍历. 
如果不是当前线程是否可以借助 API 函数 GetThreadContext 去获得指定线程的上下文. 不知道各位网友有没有验证过, 我觉得可行, 但还没有去验证.
< 注释:如果想了解更详细的信息, 建议直接去看 msdn >

大家都是程序员, 废话不多说, 请参考下面的样例代码:

  1. #include <string>
  2. #include <assert.h>

  3. #include "Windows.h"
  4. #include "dbghelp.h"
  5. #pragma comment(lib,"Dbghelp.lib")
  6. bool _printCallStark(DWORD MachineType, _EXCEPTION_POINTERS * lpEP)
  7. {
  8.     if( ! lpEP || ! SymInitialize( GetCurrentProcess(), NULL, TRUE ) )
  9.     {
  10.         return false;
  11.     }

  12.     STACKFRAME stackFrame = { 0 };
  13.     stackFrame.AddrPC.Mode = AddrModeFlat;
  14.     stackFrame.AddrPC.Offset = lpEP->ContextRecord->Eip;
  15.     stackFrame.AddrStack.Mode = AddrModeFlat;
  16.     stackFrame.AddrStack.Offset = lpEP->ContextRecord->Esp;
  17.     stackFrame.AddrFrame.Mode = AddrModeFlat;
  18.     stackFrame.AddrFrame.Offset = lpEP->ContextRecord->Ebp;
  19.     
  20.     const static size_t MAX_DEPTH = 30;
  21.     const static size_t MIN_INDEX = 3;
  22.     size_t index = 0;
  23.     while ( StackWalk (
  24.         MachineType, GetCurrentProcess(), GetCurrentThread(),
  25.         &stackFrame, lpEP->ContextRecord, NULL,
  26.         SymFunctionTableAccess, SymGetModuleBase, NULL )/*StackWalk*/)
  27.     {
  28.         if ( index++ < MIN_INDEX ) continue ;
  29.         if ( index > MAX_DEPTH ) break ;
  30.         assert( stackFrame.AddrFrame.Offset != 0);

  31.         const size_t BUF_LEN = 1024;
  32.         unsigned char * symbolBuffer = new unsigned char[sizeof( SYMBOL_INFO ) + BUF_LEN];
  33.         PSYMBOL_INFO pSymbol = reinterpret_cast<PSYMBOL_INFO>(symbolBuffer);
  34.         pSymbol->SizeOfStruct = sizeof( SYMBOL_INFO );
  35.         pSymbol->MaxNameLen = BUF_LEN;

  36.         SymFromAddr( GetCurrentProcess(), stackFrame.AddrPC.Offset, 0, pSymbol );
  37.         
  38.         IMAGEHLP_LINE lineInfo = { sizeof(IMAGEHLP_LINE) };
  39.         DWORD dwLineDisplacement;
  40.         SymGetLineFromAddr( 
  41. GetCurrentProcess(), stackFrame.AddrPC.Offset, 
  42. &dwLineDisplacement, &lineInfo );

  43.         char cstrInfo[256] = {0};
  44.         sprintf_s(cstrInfo,"%s(%d) : [threadID=%d] [function=%s]\n", 
  45. lineInfo.FileName, lineInfo.LineNumber,
  46. GetCurrentThreadId(), pSymbol->Name );
  47.         OutputDebugStringA( cstrInfo );

  48.         delete[]symbolBuffer; symbolBuffer = NULL;
  49.     }

  50.     if( ! SymCleanup( GetCurrentProcess() ) )
  51.     {
  52.         return false;
  53.     }
  54.     return true;
  55. }

  56. void printCallStark()
  57. {
  58.     __try
  59.     {
  60.         throw "";
  61.     }
  62.     __except( _printCallStark(
  63.         IMAGE_FILE_MACHINE_I386,
  64.         GetExceptionInformation() )/*printCallStark*/)
  65.     {
  66.         printf( "Some exception occures.\n" );
  67.     }
  68. }

简单的测试代码:

  1. void test_function()
  2. {
  3.     printCallStark();
  4. }

  5. int main()
  6. {
  7.     test_function();
  8.     return 0;
  9. }
输出结果如下, 双击定位到源文件相关位置.

  1. d:\src-project\basictest\basictest\main.cpp(77) : [threadID=10184] [function=test_function]
  2. d:\src-project\basictest\basictest\main.cpp(82) : [threadID=10184] [function=main]
  3. f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c(597) : [threadID=10184] [function=__tmainCRTStartup]
  4. f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c(414) : [threadID=10184] [function=mainCRTStartup]
  5. (null)(0) : [threadID=10184] [function=BaseThreadInitThunk]
  6. (null)(0) : [threadID=10184] [function=RtlInitializeExceptionChain]
  7. (null)(0) : [threadID=10184] [function=RtlInitializeExceptionChain]
  8. 程序“[7272] basicTest.exe: 本机”已退出,返回值为 0 (0x0)。

阅读(1460) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~