繁体   English   中英

在Windows中无法获取呼叫堆栈

[英]Unable to get call stack in Windows

如果出现以下代码,为什么会出现ERROR_INVALID_HANDLE错误? 我究竟做错了什么?

#include <Windows.h>
#include <DbgHelp.h>

#include <cstddef>
#include <cstring>
#include <iostream>

void print_call_stack()
{
  HANDLE cur_process_handle = GetCurrentProcess();
  HANDLE cur_thread_handle = GetCurrentThread();

  CONTEXT cur_thread_context;
  std::memset(&cur_thread_context, 0, sizeof(CONTEXT));
  cur_thread_context.ContextFlags = CONTEXT_FULL;
  if (!GetThreadContext(cur_thread_handle, &cur_thread_context))
  {
    std::cerr << "An error occurred while using function GetThreadContext. "
      << "Error code: " << GetLastError() << '\n';
    return;
  }

  STACKFRAME64 sf;
  std::memset(&sf, 0, sizeof(sf));
  sf.AddrPC.Mode         = AddrModeFlat;
  sf.AddrStack.Mode      = AddrModeFlat;
  sf.AddrFrame.Mode      = AddrModeFlat;
#ifdef _M_IX86  // Intel Only!
  sf.AddrPC.Offset       = cur_thread_context.Eip;
  sf.AddrStack.Offset    = cur_thread_context.Esp;
  sf.AddrFrame.Offset    = cur_thread_context.Ebp;
#endif
#ifdef _M_X64  // Intel Only!
  sf.AddrPC.Offset       = cur_thread_context.Rip;
  sf.AddrStack.Offset    = cur_thread_context.Rsp;
  sf.AddrFrame.Offset    = cur_thread_context.Rbp;
#endif
#ifdef _M_IA64 // Itanium
#pragma message("fix me")
  sf.AddrPC.Offset       = 0;
  sf.AddrStack.Offset    = 0;
  sf.AddrFrame.Offset    = 0;
#endif

#ifdef _M_IX86
  DWORD machine_type = IMAGE_FILE_MACHINE_I386;
#endif
#ifdef _M_X64
  DWORD machine_type = IMAGE_FILE_MACHINE_AMD64;
#endif
#ifdef _M_IA64
  DWORD machine_type = IMAGE_FILE_MACHINE_IA64;
#endif

  int count = 0;
  // According to MSDN, the sum of FramesToSkip and FramesToCapture
  // must be less than 63 in case of Windows Server 2003 and Windows XP,
  // so set it to 62
  void* trace[62];

  while (StackWalk64(
    machine_type
    , cur_process_handle
    , cur_thread_handle
    , &sf
    , &cur_thread_context
    , NULL
    , SymFunctionTableAccess64
    , SymGetModuleBase64
    , NULL
    ) == TRUE && count < sizeof(trace) / sizeof(*trace))
  {
    trace[count++] = reinterpret_cast<void*>(sf.AddrPC.Offset);
  }

  for (std::size_t i = 0; i < count; ++i)
  {
    const int kMaxNameLength = 256;
    DWORD_PTR frame = reinterpret_cast<DWORD_PTR>(trace[i]);

    ULONG64 buffer[
      (sizeof(SYMBOL_INFO) +
        kMaxNameLength * sizeof(wchar_t) +
        sizeof(ULONG64) - 1) /
        sizeof(ULONG64)];
      std::memset(buffer, 0, sizeof(buffer));

      // Initialize symbol information retrieval structures.
      DWORD64 sym_displacement = 0;
      PSYMBOL_INFO symbol = reinterpret_cast<PSYMBOL_INFO>(&buffer[0]);
      symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
      symbol->MaxNameLen = kMaxNameLength - 1;
      BOOL has_symbol = SymFromAddr(
        cur_process_handle
        , frame
        , &sym_displacement
        , symbol
      );
      if (has_symbol == FALSE)
      {
        std::cerr << "An error occurred while using function SymFromAddr."
                  << " Error code: " << GetLastError() << '\n';
      }

      // Attempt to retrieve line number information.
      DWORD line_displacement = 0;
      IMAGEHLP_LINE64 line = {};
      line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
      BOOL has_line = SymGetLineFromAddr64(
        cur_process_handle
        , frame
        , &line_displacement
        , &line
      );
      if (has_line == FALSE)
      {
        std::cerr << "An error occurred while using function SymGetLineFromAddr64."
                  << " Error code: " << GetLastError() << '\n';
      }

      if (has_symbol == TRUE)
      {
        std::cout << symbol->Name << " [0x" << trace[i] << "+"
          << sym_displacement << "]";
      }
      else
      {
        std::cout << "(No symbol) [0x" << trace[i] << "]";
      }

      if (has_line == TRUE)
      {
        std::cout << " (" << line.FileName << ":" << line.LineNumber << ")";
      }

      std::cout << '\n';
  }
}

int main()
{
  print_call_stack();
}

根据文档 ,您需要先调用SymInitialize

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM