簡體   English   中英

如何將 Win32 異常代碼轉換為字符串?

[英]How do I convert a Win32 exception code to a string?

我不情願地不得不再次處理 Win32 結構化異常。 我正在嘗試生成一個描述異常的字符串。 大部分都很簡單,但我堅持一些基本的東西:如何將異常代碼( GetExceptionCode()的結果或EXCEPTION_RECORDExceptionCode成員)轉換為描述異常的字符串?

我正在尋找可以將例如 0xC0000005 轉換為“訪問沖突”的內容。 它只是對FormatMessage()的調用嗎?

結構化異常代碼通過 NTSTATUS 編號定義。 盡管 MS 的某個人建議使用FormatMessage()將 NTSTATUS 數字轉換為字符串,但我不會這樣做。 標志FORMAT_MESSAGE_FROM_SYSTEM用於將GetLastError() 的結果轉換為字符串,因此這里沒有意義。 將標志FORMAT_MESSAGE_FROM_HMODULEntdll.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.

%0FormatMessage()視為表示消息終止符的轉義序列,而不是插入。 插入是 %1 到 %99。 這就是為什么標志FORMAT_MESSAGE_IGNORE_INSERTS沒有任何區別的原因。

您可能希望從ntdll.dll加載字符串並將其傳遞給vprintf()但您需要完全按照字符串指定的方式准備參數(例如,對於EXCEPTION_ACCESS_VIOLATION它是unsigned longunsigned longchar* )。 這種方法有一個主要缺點: ntdll.dll中參數的數量、順序或大小的任何更改都可能破壞您的代碼。

因此,將字符串硬編碼到您自己的代碼中會更安全、更容易。 我發現在沒有與我協調的情況下使用其他人准備的字符串是危險的:) 並且用於其他功能。 這只是故障的另一種可能性。

是的。 這是一個NTSTATUS ,所以使用FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_FROM_HMODULE ,並從LoadLibrary("NTDLL.DLL")傳遞HMODULE

來源:KB259693(已存檔)

正確管理某些 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

此外,您可以使用GetFirstStackTraceStringGetNextStackTraceString堆棧。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM