[英]How do I convert a Win32 exception code to a string?
我不情願地不得不再次處理 Win32 結構化異常。 我正在嘗試生成一個描述異常的字符串。 大部分都很簡單,但我堅持一些基本的東西:如何將異常代碼( GetExceptionCode()
的結果或EXCEPTION_RECORD
的ExceptionCode
成員)轉換為描述異常的字符串?
我正在尋找可以將例如 0xC0000005 轉換為“訪問沖突”的內容。 它只是對FormatMessage()
的調用嗎?
結構化異常代碼通過 NTSTATUS 編號定義。 盡管 MS 的某個人建議使用FormatMessage()將 NTSTATUS 數字轉換為字符串,但我不會這樣做。 標志FORMAT_MESSAGE_FROM_SYSTEM
用於將GetLastError() 的結果轉換為字符串,因此這里沒有意義。 將標志FORMAT_MESSAGE_FROM_HMODULE
與ntdll.dll
一起使用將導致某些代碼的結果不正確。 例如,對於EXCEPTION_ACCESS_VIOLATION
您將The instruction at 0x
獲得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
、 unsigned long
、 char*
)。 這種方法有一個主要缺點: ntdll.dll
中參數的數量、順序或大小的任何更改都可能破壞您的代碼。
因此,將字符串硬編碼到您自己的代碼中會更安全、更容易。 我發現在沒有與我協調的情況下使用其他人准備的字符串是危險的:) 並且用於其他功能。 這只是故障的另一種可能性。
是的。 這是一個NTSTATUS
,所以使用FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_FROM_HMODULE
,並從LoadLibrary("NTDLL.DLL")
傳遞HMODULE
正確管理某些 NTSTATUS 字符串具有的流格式是很復雜的。 您應該考慮使用RtlNtStatusToDosError()將其轉換為 Win32 消息,該消息位於標題 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;
}
我建議你使用 bugslayer 。 只需使用EXCEPTION_POINTERS
調用GetFaultReason
。
此外,您可以使用GetFirstStackTraceString
和GetNextStackTraceString
堆棧。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.