打印调用堆栈

来源:互联网 发布:景甜的神秘力量 知乎 编辑:程序博客网 时间:2024/05/01 07:53

java里面可以使用Throwable类来获取堆栈,示例代码如下:

    package name.xu;      public class CallStack {          public static void printCallStatck() {              Throwable ex = new Throwable();              StackTraceElement[] stackElements = ex.getStackTrace();              if (stackElements != null) {                  for (int i = 0; i < stackElements.length; i++) {                      System.out.print(stackElements[i].getClassName()+"/t");                      System.out.print(stackElements[i].getFileName()+"/t");                      System.out.print(stackElements[i].getLineNumber()+"/t");                      System.out.println(stackElements[i].getMethodName());                      System.out.println("-----------------------------------");                  }              }          }                }  

windows下使用GetThreadContext ,StackWalk,SymGetOptions ,SymFunctionTableAccess,示例代码如下:

    #include "SimpleSymbolEngine.h"      #include <windows.h>      #include <psapi.h>      #include <iostream>      #include <sstream>      #include <cstddef>      #include <dbghelp.h>      #pragma comment( lib, "dbghelp" )      static char const szRCSID[] = "$Id: SimpleSymbolEngine.cpp,v 1.4 2005/05/04 21:52:05 Eleanor Exp {1}quot;;      //////////////////////////////////////////////////////////////////////////////////////      // Singleton for the engine (SymInitialize doesn't support multiple calls)      SimpleSymbolEngine& SimpleSymbolEngine::instance()      {      static SimpleSymbolEngine theEngine;          return theEngine;      }      /////////////////////////////////////////////////////////////////////////////////////      SimpleSymbolEngine::SimpleSymbolEngine()      {          hProcess = GetCurrentProcess();          DWORD dwOpts = SymGetOptions();          dwOpts |= SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS;          SymSetOptions ( dwOpts );          ::SymInitialize( hProcess, 0, true );      }      /////////////////////////////////////////////////////////////////////////////////////      SimpleSymbolEngine::~SimpleSymbolEngine()      {          ::SymCleanup( hProcess );      }      /////////////////////////////////////////////////////////////////////////////////////      std::string SimpleSymbolEngine::addressToString( PVOID address )      {          std::ostringstream oss;          // First the raw address          oss << "0x" << address;          // Then any name for the symbol          struct tagSymInfo          {              IMAGEHLP_SYMBOL symInfo;              char nameBuffer[ 4 * 256 ];          } SymInfo = { { sizeof( IMAGEHLP_SYMBOL ) } };          IMAGEHLP_SYMBOL * pSym = &SymInfo.symInfo;          pSym->MaxNameLength = sizeof( SymInfo ) - offsetof( tagSymInfo, symInfo.Name );          DWORD dwDisplacement;          if ( SymGetSymFromAddr( hProcess, (DWORD)address, &dwDisplacement, pSym) )          {              oss << " " << pSym->Name;              if ( dwDisplacement != 0 )                  oss << "+0x" << std::hex << dwDisplacement << std::dec;          }                        // Finally any file/line number          IMAGEHLP_LINE lineInfo = { sizeof( IMAGEHLP_LINE ) };          if ( SymGetLineFromAddr( hProcess, (DWORD)address, &dwDisplacement, &lineInfo ) )          {              char const *pDelim = strrchr( lineInfo.FileName, '//' );              oss << " at " << ( pDelim ? pDelim + 1 : lineInfo.FileName ) << "(" << lineInfo.LineNumber << ")";          }          return oss.str();      }      /////////////////////////////////////////////////////////////////////////////////////      // StackTrace: try to trace the stack to the given output      void SimpleSymbolEngine::StackTrace( PCONTEXT pContext, std::ostream & os )      {          os << "  Frame       Code address/n";          STACKFRAME stackFrame = {0};          stackFrame.AddrPC.Offset = pContext->Eip;          stackFrame.AddrPC.Mode = AddrModeFlat;          stackFrame.AddrFrame.Offset = pContext->Ebp;          stackFrame.AddrFrame.Mode = AddrModeFlat;          stackFrame.AddrStack.Offset = pContext->Esp;          stackFrame.AddrStack.Mode = AddrModeFlat;          while ( ::StackWalk(             IMAGE_FILE_MACHINE_I386,             hProcess,             GetCurrentThread(), // this value doesn't matter much if previous one is a real handle             &stackFrame,              pContext,             NULL,             ::SymFunctionTableAccess,             ::SymGetModuleBase,             NULL ) )          {              os << "  0x" << (PVOID) stackFrame.AddrFrame.Offset << "  " << addressToString( (PVOID)stackFrame.AddrPC.Offset ) << "/n";          }          os.flush();      }  

完整的代码到http://www.howzatt.demon.co.uk/articles/SimpleSymbolEngine.zip下载。http://www.codeproject.com/KB/threads/StackWalker.aspx里面也有例子。

 

参考:

http://www.diybl.com/course/3_program/java/javashl/2008119/96739.html

http://topic.csdn.net/u/20090618/11/7c19832a-975e-4be6-987b-e61d789b31b5.html

http://bbs3.chinaunix.net/viewthread.php?tid=950357&extra=&page=2

http://www.codeproject.com/KB/threads/StackWalker.aspx

http://topic.csdn.net/u/20070515/21/fc3ebc11-b871-4761-90ae-3c6ddc7b4248.html

http://www.diybl.com/course/3_program/c++/cppjs/20090403/163752_2.html

http://accu.org/index.php/journals/276

http://blog.thepimp.net/archives/how-to-generate-backtraces-on-windows-without-compiler.html

http://blog.csdn.net/chief1985/article/details/4618492