【问题标题】:SymGetSymFromAddr64 works but SymGetLineFromAddr64 fails with error code 487SymGetSymFromAddr64 有效,但 SymGetLineFromAddr64 失败,错误代码为 487
【发布时间】:2015-10-16 17:22:02
【问题描述】:

我正在学习 Windows 7 中“DbgHelp”提供的 StackWalk API。我编写了一个使用 StackWalk64 的异常过滤器。目的是使用函数名称和行号最多回溯 50 行。 “StackWalk64”遍历每个堆栈帧。从堆栈帧检索到的地址(AddrPC)用于“SymGetSymFromAddr64”和“SymGetLineFromAddr64”分别检索符号名称和行号。但是,尽管“SymGetSymFromAddr64”工作成功,“SymGetLineFromAddr64”却失败了。最后返回的错误是 487。地址如何能成功地为前者工作,但不能为后者工作?

我错过了什么吗?有什么帮助吗?

LONG WINAPI TestStackWalker (EXCEPTION_POINTERS* lpFilter)
{
   STACKFRAME64 st;
   CONTEXT cc;
   HANDLE hProcess = ::GetCurrentProcess();
   HANDLE hThread = ::GetCurrentThread();

   vector<IMAGEHLP_SYMBOL64> vectSymbs(50);
   vector<IMAGEHLP_LINE64> vectLines(50);

   if (!SymInitialize(hProcess, NULL, TRUE))
   {
      cout << "Issue with SymInitialize ! " << ::GetLastError() << endl;
      return 1;
   } 

   cc = *(lpFilter->ContextRecord);

   printContext(cc);

   ::ZeroMemory(&st, sizeof(st));

   st.AddrStack.Mode = AddrModeFlat;
   st.AddrStack.Offset = cc.Esp;
   st.AddrFrame.Mode = AddrModeFlat;
   st.AddrFrame.Offset = cc.Ebp;
   st.AddrPC.Mode = AddrModeFlat;
   st.AddrPC.Offset = cc.Eip;

   for (int i = 0; i < 50; i++)
   {
      if (!::StackWalk64(IMAGE_FILE_MACHINE_I386,
         hProcess,
         hThread,
         &st,
         &cc,
         NULL,
         SymFunctionTableAccess64,
         SymGetModuleBase64,
         NULL))
      {
         cout <<  "Issue with StackWalkFailed: " << ::GetLastError () <<endl;
         return 1;
      }

      if (st.AddrReturn.Offset == st.AddrPC.Offset)
      {
         cout << "i think it's done!" << endl;
         break;
      }

      if (st.AddrPC.Offset != 0)
      {

         vectSymbs[i].SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
         vectSymbs[i].MaxNameLength = 1024;
         if (!SymGetSymFromAddr64 (hProcess, st.AddrPC.Offset, 0, &vectSymbs[i]))
         {
            cout << "Issue with Getting Symbol From Address " << ::GetLastError() << endl;
            break;
         }

         SymSetOptions(SYMOPT_LOAD_LINES);

         vectLines[i].SizeOfStruct = sizeof(IMAGEHLP_LINE64);

         if (!SymGetLineFromAddr64 (hProcess, st.AddrPC.Offset, 0, &vectLines[i]))
         {
            cout << "Issue with Getting Line from Address " << ::GetLastError() << endl;
            break;
         }

         cout << vectSymbs[i].Name << " at " << vectLines[i].LineNumber <<endl;

      }

      if (st.AddrReturn.Offset ==  0)
      {
         cout << "seems finished " << endl;
         break;
      }
   }
   return 1;
}

【问题讨论】:

  • 只是一个观察,但vector&lt;IMAGEHLP_SYMBOL64&gt; vectSymbs(50); 是不对的。你有一个超出范围的错误。如果你做vectSymbs[i].MaxNameLength = 1024;,那么你必须有一个包含那个空格的类型。一种稍微幼稚但简单的方法是声明一个类型struct IMAGEHLP_SYMBOL64_1024 : IMAGEHLP_SYMBOL64 { char rest[1024 - 1]; }; 这将根据对齐方式过度分配几个字节,但至少它不会分配不足。然后将该类型用于vector 的模板参数。

标签: c++ windows debugging exception-handling


【解决方案1】:

pdwDisplacement 参数不是可选的:

     DWORD dis;
     if (!SymGetLineFromAddr64 (hProcess, st.AddrPC.Offset, &dis, &vectLines[i]))
     {
        cout << "Issue with Getting Line from Address " << ::GetLastError() << endl;
        break;
     }

【讨论】:

    【解决方案2】:

    我遇到了同样的问题。我的符号在符号服务器上。解决方案是将 symsrv.dll(来自 Windows SDK)放在 dbghelp.dll 旁边,以便加载它。之后一切正常。在实践中,解决方案是将 dbghelp.dll 和 symsrv.dll 与我的应用程序一起分发(连同 dbgcore.dll 和 srcsrv.dll)。请参阅 Visual Studio 中的模块列表,以验证 symsrv.dll 和 dbghelp.dll 是否从您期望的位置加载。

    更多信息在这里:

    【讨论】:

      猜你喜欢
      • 2014-10-15
      • 2021-12-04
      • 1970-01-01
      • 2012-03-15
      • 1970-01-01
      • 1970-01-01
      • 2013-05-28
      • 2014-04-24
      • 2020-07-12
      相关资源
      最近更新 更多