C或者C++開發肯定經常會遇到各種錯誤碼,由於每個錯誤碼只是一個枚舉或者一個整形數值,調試或者輸出日志的時候,無法知道這個錯誤碼的具體含義,這時候就需要將此錯誤碼解釋出來。對於自己定義的錯誤碼,可以通過自己的方式進行解析。對於Windows API的錯誤碼,則需要調用Windows的API進行解析,下面來介紹具體的錯誤碼解析方法。
調用Windows API失敗後,通常需要通過GetLastError來獲取對應的錯誤碼,要將此錯誤碼解析為對應的描述信息,則需要調用另外一個Windows API FormatMessage,原型如下:
DWORD WINAPI FormatMessage( _In_ DWORD dwFlags, _In_opt_ LPCVOID lpSource, _In_ DWORD dwMessageId, _In_ DWORD dwLanguageId, _Out_ LPTSTR lpBuffer, _In_ DWORD nSize, _In_opt_ va_list *Arguments );
具體的參數意義就不在這裡介紹了,直接查看MSDN即可,下面來看一下具體的使用方法示例:
char msg[1024] = { 0 }; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, 5, LANG_NEUTRAL, msg, _countof(msg), NULL); cout << msg << endl;
運行程序即可看到對應的錯誤描述:拒絕訪問。
程序在運行的時候,難免會產生一些異常,通過Windows的SEH機制可以得到此異常信息,其中會包含一個異常值,比如0xC0000008。如果用上面提到的FormatMessage的方式,獲取到的消息是一個字符串,或者無法獲取到此異常值的描述。那麼如何獲取這個異常值的描述呢,仔細看FormatMessage API的MSDN文檔,可以看到有這樣一個標志:
FORMAT_MESSAGE_FROM_HMODULE
這個標志的意思是:可以通過其他模塊,來解釋此異常值或者錯誤碼。
那麼什麼模塊會包含Windows異常值的定義和解釋呢,通過谷歌或者MSDN可以知道,是“ntdll.dll”。
知道了這些,就可以寫程序來解釋Windows異常值了,代碼如下:
char msg[1024] = { 0 }; HMODULE hntdll = LoadLibrary("NTDLL.DLL"); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE, hntdll, 0xC0000008, LANG_NEUTRAL, msg, _countof(msg), NULL); FreeLibrary(hntdll); cout << msg << endl;
當的程序中確實需要對Windows錯誤碼和Windows異常值進行解析的時候,就可以使用上面的方法進行解析。
但是當我們只是簡單的想看看一個錯誤碼的解釋的時候,難道還必須寫一個程序來解釋嗎。
微軟也考慮到了你正在思考的這一點,所以在安裝了VS後,都會附帶一個小工具,用來解釋錯誤碼,叫做:ErrLook,一般可以在VS的工具菜單中看到,或者可以在“VS目錄\Common7\Tools”目錄下找到這個程序,如下:
FormatMessage function
How to translate NTSTATUS error codes to message strings