我不情愿地再次处理Win32结构化异常。我正在尝试生成描述异常的字符串。大部分都是直截了当的,但我坚持一些基本的东西:如何转换异常代码(结果 GetExceptionCode()
, 或者 ExceptionCode
成员 EXCEPTION_RECORD
)进入描述异常的字符串?
我正在寻找能够将例如0xC0000005转换为“访问冲突”的东西。这只是一个电话 FormatMessage()
?
我不情愿地再次处理Win32结构化异常。我正在尝试生成描述异常的字符串。大部分都是直截了当的,但我坚持一些基本的东西:如何转换异常代码(结果 GetExceptionCode()
, 或者 ExceptionCode
成员 EXCEPTION_RECORD
)进入描述异常的字符串?
我正在寻找能够将例如0xC0000005转换为“访问冲突”的东西。这只是一个电话 FormatMessage()
?
是。它是 NTSTATUS
,所以使用 FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_FROM_HMODULE
,并通过 HMODULE
从 LoadLibrary("NTDLL.DLL")
结构化异常代码通过NTSTATUS编号定义。虽然有人来自MS 提示 运用 的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,但您需要准确准备与字符串指定的参数(例如for EXCEPTION_ACCESS_VIOLATION
它的 unsigned long
, unsigned long
, char*
)。这种方法有一个主要的缺点:参数的数量,顺序或大小的任何变化 ntdll.dll
可能会破坏你的代码。
因此,将字符串硬编码到您自己的代码中更安全,更容易。我发现使用别人准备的字符串而不与我协调是危险的:)而且还有其他功能。这只是故障的另一种可能性。
正确管理一些NTSTATUS字符串所具有的流格式很复杂。您应该考虑将其转换为Win32消息 RtlNtStatusToDosError(),标题为Winternl.h。您需要在链接器输入中使用ntdll.lib。
示例实现:
// Returns length of resulting string, excluding null-terminator.
// Use LocalFree() to free the buffer when it is no longer needed.
// Returns 0 upon failure, use GetLastError() to get error details.
DWORD FormatNtStatus(NTSTATUS nsCode, TCHAR **ppszMessage) {
// Get handle to ntdll.dll.
HMODULE hNtDll = LoadLibrary(_T("NTDLL.DLL"));
// Check for fail, user may use GetLastError() for details.
if (hNtDll == NULL) return 0;
// Call FormatMessage(), note use of RtlNtStatusToDosError().
DWORD dwRes = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE,
hNtDll, RtlNtStatusToDosError(nsCode), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)ppszMessage, 0, NULL);
// Free loaded dll module and decrease its reference count.
FreeLibrary(hNtDll);
return dwRes;
}