当程序与符号名称一起崩溃时,输出呼叫堆栈
Output the call stack when the program crashes along with the symbol names
我想在捕获未手动异常并且程序崩溃时输出呼叫堆栈。我想在程序还活着的情况下,没有任何验尸分析。
我宁愿不使用任何第三方库,这是对类似问题的大多数答案。我正在尝试在这里使用stackwalk。
我试图让它在Windows上工作。
这就是我所拥有的:
DWORD machine = IMAGE_FILE_MACHINE_I386;
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
CONTEXT context = {};
context.ContextFlags = CONTEXT_FULL;
RtlCaptureContext(&context);
SymInitialize(process, NULL, TRUE);
SymSetOptions(SYMOPT_LOAD_LINES);
STACKFRAME frame = {};
frame.AddrPC.Offset = context.Eip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = context.Ebp;
frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrStack.Offset = context.Esp;
frame.AddrStack.Mode = AddrModeFlat;
while (StackWalk(machine, process, thread, &frame, &context, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL))
{
char * functionName;
char symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 255];
PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
symbol->SizeOfStruct = (sizeof IMAGEHLP_SYMBOL) + 255;
symbol->MaxNameLength = 254;
if (SymGetSymFromAddr(process, frame.AddrPC.Offset, NULL, symbol))
{
functionName = symbol->Name;
std::string str(functionName);
std::wstring stemp = std::wstring(str.begin(), str.end());
LPCWSTR sw = stemp.c_str();
MessageBox(NULL, sw, L"Error", MB_ICONERROR | MB_OK); //for testing purposes
if (str.find("nvd3dum") != std::string::npos) {
//I'd put a messagebox here telling the user to do something if I find a symbol name I recognize
}
}
}
我遇到的问题是,我没有在程序崩溃时输出呼叫堆栈,而是得到了我在此非常函数中使用的rtlcapturecontext之类的功能。
<</p>我解决了它。我见过很多人和我有同样的问题。将其置于正确的上下文中!
CONTEXT context = {};
context.ContextFlags = exceptionInfo->ContextRecord->ContextFlags;
context.Eip = exceptionInfo->ContextRecord->Eip;
context.Ebp = exceptionInfo->ContextRecord->Ebp;
context.Esp = exceptionInfo->ContextRecord->Esp;
原则上,呼叫堆栈不需要在C 中存在。仔细阅读C 11标准N3337,那里没有提及呼叫堆栈。因此,从理论上讲,某些C 编译器可以足够聪明,可以避免任何呼叫堆栈(对于该编译器提供的某些特定程序)。许多C 编译器正在优化尾声(因此在调用函数和其呼叫框架之间共享相同的内存位置)。
实际上,C 实现遵循AS-IF规则。他们可以并且经常可以优化到内部函数的点,即使您没有使用inline
注释的功能。发生这种情况时,谈到嵌入函数的呼叫框架是没有道理的。
还要注意一些自动变量实际上不在呼叫堆栈上。允许编译器(并且通常)仅将某些变量放入处理器寄存器中,而不会将它们溢出到呼叫堆栈中。阅读有关注册分配的信息。您的呼叫框架中的一个给定插槽可用于保持几个无关的变量。
因此,显示呼叫堆栈是一个实施质量问题,可能取决于 external 因素(例如,在编译C 代码时所需的优化级别)。在Linux上,我建议使用Ian Taylor Libbacktrace。我想您可以在Windows上找到一个类似的库进行调用堆栈检查。
相关文章:
- 递归函数计算序列中的平方和(并输出过程)
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 请解释"函数1(p1,p2,p3);"的输出
- C++:将控制台输出存储在宏中更好吗
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 为什么我的代码在输出中增加了93天
- 如何从void函数输出字符串
- 输入到文件并输出到另一个文件,并将流文件传递给函数
- 呼叫运营商<<临时
- AES加密到解密未正确输出
- 如何将c++程序的一些输出传递给shell,以便在shell中使用
- 使用C++程序合并排序没有得到正确的输出
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- C++格式化输出问题
- 将值从二维数组输出到文本文件
- 集合上的输出迭代器:assign和increment迭代器
- 在while循环中输入带有std::cin的字符串后,控制台会输出大量胡言乱语
- 如何将QString绑定到QSQLQUERY,该呼叫过程输出VARCHAR
- 当程序与符号名称一起崩溃时,输出呼叫堆栈