windows 是否有将 EXCEPTION_POINTERS 结构转换为字符串的函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3523716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a function to convert EXCEPTION_POINTERS struct to a string?
提问by John MacIntyre
Does anybody know of a function to convert the EXCEPTION_POINTERS structure returned from GetExceptionInformation() into a string that I can log?
有人知道将 GetExceptionInformation() 返回的 EXCEPTION_POINTERS 结构转换为我可以记录的字符串的函数吗?
I don't want to roll my own if it's already been done.
如果已经完成,我不想自己动手。
EDIT: Basically, I've added the __try{} __except(){} blocks to help the app fail gracefully on a critical error. While I'm at it, I'm trying to log as detailed of an error message as possible to locate the issue for us to resolve. Ideally, I'd like to print out the file name and line it failed on, but I doubt that's possible, so I'm hoping to dump all the exception information in the hopes that we'll be able to come as close as possible to pinpointing the exact cause of the problem.
编辑:基本上,我添加了 __try{} __except(){} 块来帮助应用程序在出现严重错误时正常失败。在此期间,我会尝试尽可能详细地记录错误消息,以找到需要我们解决的问题。理想情况下,我想打印出失败的文件名和行,但我怀疑这是可能的,所以我希望转储所有异常信息,希望我们能够尽可能接近以查明问题的确切原因。
采纳答案by Ana Betts
There is no such function, since you'll need private symbols to write anything meaningful. The dbghelp.dll helps with some of this (specifically the StackWalk functionand its 64-bit variant)
没有这样的功能,因为您需要使用私有符号来编写任何有意义的内容。dbghelp.dll 有助于解决其中的一些问题(特别是StackWalk 函数及其 64 位变体)
What do you want to get out of the exception record to put into the log? Just the exception code? The register context? The stack backtrace?
你想从异常记录中取出什么放入日志?只是异常代码?寄存器上下文?堆栈回溯?
EDIT:Also, if you just do nothing, but register for Windows Error Reporting, you can just use Microsoft's awesome service and get the crash dumps back, bucketed by popularity. If you can, that's by-far the best way to record crash dumps.
编辑:此外,如果您什么都不做,只注册Windows Error Reporting,您就可以使用 Microsoft 出色的服务并恢复崩溃转储,受流行程度的影响。如果可以,这是迄今为止记录故障转储的最佳方式。
回答by Alessandro Jacopson
// Compile with /EHa
#include <windows.h>
#include <eh.h>
#include <Psapi.h>
#include <string>
#include <sstream>
class InfoFromSE
{
public:
typedef unsigned int exception_code_t;
static const char* opDescription( const ULONG opcode )
{
switch( opcode ) {
case 0: return "read";
case 1: return "write";
case 8: return "user-mode data execution prevention (DEP) violation";
default: return "unknown";
}
}
static const char* seDescription( const exception_code_t& code )
{
switch( code ) {
case EXCEPTION_ACCESS_VIOLATION: return "EXCEPTION_ACCESS_VIOLATION" ;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED" ;
case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT" ;
case EXCEPTION_DATATYPE_MISALIGNMENT: return "EXCEPTION_DATATYPE_MISALIGNMENT" ;
case EXCEPTION_FLT_DENORMAL_OPERAND: return "EXCEPTION_FLT_DENORMAL_OPERAND" ;
case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO" ;
case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT" ;
case EXCEPTION_FLT_INVALID_OPERATION: return "EXCEPTION_FLT_INVALID_OPERATION" ;
case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW" ;
case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK" ;
case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW" ;
case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION" ;
case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR" ;
case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO" ;
case EXCEPTION_INT_OVERFLOW: return "EXCEPTION_INT_OVERFLOW" ;
case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION" ;
case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "EXCEPTION_NONCONTINUABLE_EXCEPTION" ;
case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION" ;
case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP" ;
case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW" ;
default: return "UNKNOWN EXCEPTION" ;
}
}
static std::string information( struct _EXCEPTION_POINTERS* ep, bool has_exception_code = false, exception_code_t code = 0 )
{
HMODULE hm;
::GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, static_cast<LPCTSTR>(ep->ExceptionRecord->ExceptionAddress), &hm );
MODULEINFO mi;
::GetModuleInformation( ::GetCurrentProcess(), hm, &mi, sizeof(mi) );
char fn[MAX_PATH];
::GetModuleFileNameExA( ::GetCurrentProcess(), hm, fn, MAX_PATH );
std::ostringstream oss;
oss << "SE " << (has_exception_code?seDescription( code ):"") << " at address 0x" << std::hex << ep->ExceptionRecord->ExceptionAddress << std::dec
<< " inside " << fn << " loaded at base address 0x" << std::hex << mi.lpBaseOfDll << "\n";
if ( has_exception_code && (
code == EXCEPTION_ACCESS_VIOLATION ||
code == EXCEPTION_IN_PAGE_ERROR ) ) {
oss << "Invalid operation: " << opDescription(ep->ExceptionRecord->ExceptionInformation[0]) << " at address 0x" << std::hex << ep->ExceptionRecord->ExceptionInformation[1] << std::dec << "\n";
}
if ( has_exception_code && code == EXCEPTION_IN_PAGE_ERROR ) {
oss << "Underlying NTSTATUS code that resulted in the exception " << ep->ExceptionRecord->ExceptionInformation[2] << "\n";
}
return oss.str();
}
};
#include <iostream>
#include <exception>
void translator( InfoFromSE::exception_code_t code, struct _EXCEPTION_POINTERS* ep )
{
throw std::exception( InfoFromSE::information(ep,true,code).c_str() );
}
int main(int argc, char* argv[])
{
_set_se_translator(translator);
try{
int* p = 0;
std::cout << *p;
}catch( const std::exception& e ){
std::cerr << e.what() << "\n";
}
try{
int* p = 0;
*p = 0;
std::cout << *p;
}catch( const std::exception& e ){
std::cerr << e.what() << "\n";
}
try{
int a = 42;
volatile int b = 0;
std::cout << a/b;
}catch( const std::exception& e ){
std::cerr << e.what() << "\n";
}
return 0;
}
回答by Knowles Atchison
#include <windows.h>
#include <iostream>
#include <string.h>
#include <eh.h>
using namespace std;
static void translateSEH(unsigned int u, EXCEPTION_POINTERS* pExcept) {
// Translate SEH exception to a C++ exception. NOTE: compiling with /EHa is required!!
static char msg[256];
sprintf_s(msg, 256, "Unhandled exception 0x%08x at 0x%08x",
pExcept->ExceptionRecord->ExceptionCode,
pExcept->ExceptionRecord->ExceptionAddress);
throw exception(msg);
}
int main(){
_set_se_translator(translateSEH);
int p = 0;
try {
cout<<1 / p<<endl;
}
catch (std::exception& ex) {
cout << ex.what() << endl;
}
}
回答by Hans Passant
There isn't much to it, you'll only be interested in the exception code and address. If the exception is an EXCEPTION_ACCESS_VIOLATION then you also want to dump the first two ExceptionInformation values. The first one indicates the operation (0=read, 1=write, 8=data execution prevention), the second one gives the fault address.
没有太多内容,您只会对异常代码和地址感兴趣。如果异常是 EXCEPTION_ACCESS_VIOLATION,那么您还想转储前两个 ExceptionInformation 值。第一个表示操作(0=读,1=写,8=数据执行阻止),第二个给出故障地址。
回答by jlguenego
You can see the microsoft code at : http://support.microsoft.com/kb/259693You can also check this small piece of code: http://www.codeproject.com/Articles/6503/An-NTSTATUS-lookup-application
您可以在以下位置查看 microsoft 代码:http: //support.microsoft.com/kb/259693您还可以查看这段代码:http: //www.codeproject.com/Articles/6503/An-NTSTATUS-lookup -应用