如何在不使用将字符串硬编码到应用程序中的情况下获取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
”。
答案 0 :(得分:2)
结构化异常代码通过NTSTATUS编号定义。虽然来自MS suggests的某人使用FormatMessage()将NTSTATUS号码转换为字符串,但我不会这样做。标记FORMAT_MESSAGE_FROM_SYSTEM
用于将GetLastError()的结果转换为字符串,因此这里没有意义。使用标记FORMAT_MESSAGE_FROM_HMODULE
和ntdll.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.
%0
被FormatMessage()视为转义序列,意味着消息终止符,而不是插入。插入是%1到%99。这就是为什么标志FORMAT_MESSAGE_IGNORE_INSERTS
没有任何区别。
您可能希望从ntdll.dll
加载字符串并将其传递给vprintf,但您需要准确准备与字符串指定的参数(例如,对于EXCEPTION_ACCESS_VIOLATION
它是unsigned long
,{{ 1}},unsigned long
)。这种方法有一个主要缺点:char*
中参数的数量,顺序或大小的任何变化都可能会破坏您的代码。
因此,将字符串硬编码到您自己的代码中会更安全,更容易。我发现使用别人准备的字符串而不与我协调是危险的:)而且还有其他功能。这只是故障的另一种可能性。
答案 1 :(得分:1)