如何获取例外的名称/描述?

时间:2008-11-26 19:38:14

标签: windows winapi exception

如何在不使用将字符串硬编码到应用程序中的情况下获取SEH例外的名称和/或描述?

我尝试使用FormatMessage(),但有时会截断消息,即使您指定忽略插入:

__asm { // raise access violation
    xor    eax, eax
    mov    eax, [eax]
}

使用代码0xC0000005 (EXCEPTION_ACCESS_VIOLATION)引发异常。

char msg[256];
FormatMessageA(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
    GetModuleHandleA("ntdll.dll"), 0xC0000005,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    msg, sizeof(msg), NULL);

使用截断的字符串填充msg:“The instruction at 0x”。

2 个答案:

答案 0 :(得分:2)

结构化异常代码通过NTSTATUS编号定义。虽然来自MS suggests的某人使用FormatMessage()将NTSTATUS号码转换为字符串,但我不会这样做。标记FORMAT_MESSAGE_FROM_SYSTEM用于将GetLastError()的结果转换为字符串,因此这里没有意义。使用标记FORMAT_MESSAGE_FROM_HMODULEntdll.dll会导致某些代码的结果不正确。例如,对于EXCEPTION_ACCESS_VIOLATION,您将获得The instruction at 0x,这不是非常有用的信息:)。

当您查看ntdll.dll中存储的字符串时,很明显其中许多字符串应该与printf()函数一起使用,而不是与FormatMessage()一起使用。例如,EXCEPTION_ACCESS_VIOLATION的字符串是:

The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.

%0FormatMessage()视为转义序列,意味着消息终止符,而不是插入。插入是%1到%99。这就是为什么标志FORMAT_MESSAGE_IGNORE_INSERTS没有任何区别。

您可能希望从ntdll.dll加载字符串并将其传递给vprintf,但您需要准确准备与字符串指定的参数(例如,对于EXCEPTION_ACCESS_VIOLATION它是unsigned long,{{ 1}},unsigned long)。这种方法有一个主要缺点:char*中参数的数量,顺序或大小的任何变化都可能会破坏您的代码。

因此,将字符串硬编码到您自己的代码中会更安全,更容易。我发现使用别人准备的字符串而不与我协调是危险的:)而且还有其他功能。这只是故障的另一种可能性。

答案 1 :(得分:1)