一、Win32錯誤
也就是Win32子系統產生的錯誤。當我們在自己的代碼里調用Windows系統的API函數,系統執行API內部代碼,當API內部代碼出現錯誤,會將預先定義好的錯誤代碼寫到調用這個API的線程局部存儲區域(這個區域是每個線程獨有的其他線程無法更改。它存儲着一些線程獨有的東西),然后API返回,返回值告訴我們該API執行失敗了。如果我們的代碼加了檢測,發現了API失敗,這時我們調用GetLastError() 函數去獲取這個錯誤代碼,這個錯誤代碼是一個DWORD值。如果我們不及時獲取,就會被后面調用的API所覆蓋。當我們想在自己的函數里借用這種機制時,可以調用SetLastError函數來設置一個錯誤代碼。
這里我們提到了兩個API:
- DWORD GetLastError(VOID)
- void SetLastError(DWORD dwErrCode)
二、Win32 Error Code
所有Win32錯誤代碼都必須在0x0000到0xFFFF范圍內,盡管Win32錯誤代碼可以同時用於16位字段和32位字段,我們通常還是用32位來表示。大多數值已經定義了默認錯誤消息,可用於將值映射到我們可以讀懂的文本消息。它的構成如下:
雖然win32子系統錯誤的位域有32bit,但受限於值的范圍,也只能是0x00000000---0x0000FFF,也就是上面的位域高16bit都是0。
三、獲取錯誤具體信息
通過前面的說明我們了解了錯誤代碼的獲取,以及錯誤代碼和信息是怎么制作出來的,那么當我們用GetLastError獲取到錯誤代碼后,我們只是有了一個編號,還是不了解具體什么原因什么錯誤,這時,我們該用到另外一個函數了FormatMessage。
原型:
DWORD
WINAPI FormatMessage (
DWORD
dwFlags,
// source and processing options
LPCVOID
lpSource,
// message source
DWORD
dwMessageId,
// message identifier
DWORD
dwLanguageId,
// language identifier
LPTSTR
lpBuffer,
// message buffer
DWORD
nSize,
// maximum size of message buffer
va_list
*Arguments
// array of message inserts
);
它的功能就是將
GetLastError函數得到的錯誤信息(這個錯誤信息是數字代號)轉化成字符串信息的函數。
四、總結
我們可以自定義錯誤代碼和信息,通過SetLastError來實現我們自己的代碼的錯誤處理機制,然后通過系統API或自定義函數的返回值,檢測函數是否失敗,若失敗,通過GetLastError函數獲取線程里當前的錯誤代碼,在通過
FormatMessage
來查詢錯誤信息,寫到我們自己的日志里,來幫助我們調試程序的功能性和業務性問題。