【发布时间】: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<IMAGEHLP_SYMBOL64> vectSymbs(50);是不对的。你有一个超出范围的错误。如果你做vectSymbs[i].MaxNameLength = 1024;,那么你必须有一个包含那个空格的类型。一种稍微幼稚但简单的方法是声明一个类型struct IMAGEHLP_SYMBOL64_1024 : IMAGEHLP_SYMBOL64 { char rest[1024 - 1]; };这将根据对齐方式过度分配几个字节,但至少它不会分配不足。然后将该类型用于vector的模板参数。
标签: c++ windows debugging exception-handling