对程序错误的处理——Windows核心编程学习手札之一
對程序錯誤的處理
——Windows核心編程學(xué)習(xí)手札之一
函數(shù)被調(diào)用執(zhí)行時,先檢驗(yàn)傳遞給它的各個參數(shù)的有效性,后執(zhí)行任務(wù)。函數(shù)執(zhí)行中若因參數(shù)無效或因某種原因?qū)е聼o法正常完成函數(shù)任務(wù),那么操作系統(tǒng)會返回一個值,以提示函數(shù)運(yùn)行失敗。這個思想可歸納為:函數(shù)錯誤提示的透明,同樣適用于個人編寫的函數(shù),在函數(shù)執(zhí)行任務(wù)的每個關(guān)鍵點(diǎn)設(shè)置錯誤提示并返回。對所返回的錯誤代碼或提示對于正確定位和調(diào)試函數(shù)失敗點(diǎn)是非常有用的。
Microsoft給出了一個所有可能的錯誤代碼列表,并為每個錯誤代碼分配一個32位的號碼。Windows函數(shù)常用的返回值類型有VOID/BOOL/HANDLE/PVOID/LONG/DWORD,基于此,個人編寫的程序也可以維護(hù)一張自己的錯誤代碼列表,并設(shè)定返回類型。
當(dāng)函數(shù)檢測到錯誤時,會使用線程本地存儲器(thread-local storage)機(jī)制,將相應(yīng)的錯誤代碼號碼與調(diào)用的線程關(guān)聯(lián)起來,這使線程能夠互相獨(dú)立地運(yùn)行,而不影響各自的錯誤代碼。Windows函數(shù)返回時,其返回值就能指明一個錯誤已經(jīng)發(fā)生。若要確定發(fā)生的錯誤是什么,可調(diào)用函數(shù):
DWORD GetLastError();
該函數(shù)返回線程的32位錯誤代碼。有了32位錯誤代碼的號碼,便可以將該號碼轉(zhuǎn)換成更有用的信息。WinError.h頭文件包含了Microsoft定義的錯誤代碼列表。當(dāng)函數(shù)運(yùn)行失敗時,應(yīng)立即調(diào)用GetLastError函數(shù),因?yàn)槿绻{(diào)用另一個Windows函數(shù),它的值很可能被改寫。
有些函數(shù)可能返回了正確的代碼,但并不表明函數(shù)實(shí)際運(yùn)行成功,其中有很多原因。如,創(chuàng)建指明的事件內(nèi)核對象之所以成功,是因?yàn)閷?shí)際上已經(jīng)創(chuàng)建了該對象或已經(jīng)存在帶有相同名字的事件內(nèi)核對象。
程序調(diào)試中,對線程的最后錯誤代碼進(jìn)行提取和分析是非常有用的。在Microsoft Visual studio6.0中,Microsoft的調(diào)試程序可以配置Watch窗口,以便始終顯示線程的最后錯誤代碼及其英文描述。操作是在Watch窗口中的一行輸入“@err,hr”即可。Visual studio還提供一個實(shí)用程序Error Lookup可以將錯誤代碼的號碼轉(zhuǎn)換成相應(yīng)的文本描述。個人在用Microsoft Visual C++6.0開發(fā)的單元調(diào)試中經(jīng)常用到Watch窗口和Error Lookup來查看最后錯誤代碼,當(dāng)然Watch窗口的作用還不僅僅是查看錯誤代碼及其描述。
同時Windows提供一個函數(shù)FormatMessage可以將錯誤代碼轉(zhuǎn)換成它的文字描述。
DWORD FormatMessage(
??????????? DWORD dwFlags,
??????????? LPCVOID pSource,
??????????? DWORD dwMessageID,
??????????? DWORD dwLanguageID,
??????????? PTSTR pszBuffer,
??????????? DWORD nSize,
??????????? va_list *Arguments);
FormatMessage函數(shù)能夠檢測出用戶首選的語言,并返回相應(yīng)的文本。對于Microsoft是否應(yīng)該建立一個主控列表,以顯示每個Windows函數(shù)可能返回的所有錯誤代碼,可從下面兩方面來否定:一是創(chuàng)建新系統(tǒng)版本時,建立和維護(hù)該主控列表太困難;二是函數(shù)在內(nèi)部調(diào)用另一函數(shù),而這一函數(shù)同樣內(nèi)部調(diào)用其他函數(shù),如此類推,其中任何一個函數(shù)運(yùn)行失敗,調(diào)用函數(shù)都可能恢復(fù)并執(zhí)行工作,而Microsoft需要跟蹤每個函數(shù)的運(yùn)行路徑,并建立所有可能的錯誤代碼列表。
實(shí)際上我們在使用Win32的開發(fā)環(huán)境中,調(diào)用Windows函數(shù)可以利用GetLastError函數(shù)來知道所調(diào)用的Windows函數(shù)錯誤所指,而對自己的函數(shù)則需要自己編寫錯誤代碼,或說維護(hù)自己的錯誤代碼列表,以便與Windows函數(shù)一樣可以定位錯誤。換句話說,可以將Windows函數(shù)告訴調(diào)用者指明發(fā)生的錯誤的機(jī)制用于自己的函數(shù)體系。一方面可以利用Windows已有的錯誤代碼,在某個函數(shù)可能出現(xiàn)錯誤的地方設(shè)置最后錯誤代碼并返回,可采用Windows函數(shù):
VOID SetLastError(DWORD dwErrCode);
那么可以用WinError.h中代碼,只要該代碼可能說明錯誤思想并讓調(diào)用者理解即可,如想反映句柄無效,可以設(shè)置錯誤代碼為6,錯誤代碼是32位的數(shù)字。
另一方面你認(rèn)為有必要維護(hù)自己的錯誤列表,或WinError.h中的錯誤不足以反映你程序的錯誤性質(zhì),可以創(chuàng)建自己的代碼,Microsoft規(guī)定,該公司建立的所有錯誤代碼在第29位的信息位使用0,用戶自己創(chuàng)建的使1,可以確保自己的錯誤代碼與Microsoft不沖突。具體錯誤代碼域可如下:
? 位??? 31~30??????? 29?????????????? ?28?????? ???27~16????????? 15~0
內(nèi)容??? 嚴(yán)重性?????? Microsoft/客戶????? 保留??????? 設(shè)備代碼??????? 異常代碼
含義??? 0=成功?????? 0=Microsoft公司??? 必須是0??? 由Microsoft???? 由Microsoft
公司定義????? 公司定義
定義的代碼??????????????????
??????? 1=供參考???? 1=客戶定義代碼
??????? 2=警告
??????? 3=錯誤
這里模擬了Microsoft Visual C6.0中Error Lookup程序,利用MFC基于對話框的程序?qū)崿F(xiàn),主要實(shí)現(xiàn)代碼如下:
?
void CErrorShowDlg::OnBtnLookUp()
{
?????? // TODO: Add your control notification handler code here
?????? //Get the error code
?????? BOOL bRetErrorCode;
?????? DWORD dwErrorCode=GetDlgItemInt(IDC_EdtErrorCode,&bRetErrorCode,FALSE);
?????? if(!bRetErrorCode)//無值
?????? {
????????????? AfxMessageBox("輸入錯誤的代碼!");
????????????? return;
?????? }
?????? //Get the error code's textual description
?????? HLOCAL hLocal=NULL;
?????? BOOL bRetErrorText=FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
????????????? ??????????? ?????????????????NULL,dwErrorCode,MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),
?????????????????????????????????????????????????????????????? ?(LPTSTR)&hLocal,0,NULL);
?????? if(hLocal != NULL)
?????? {
????????????? SetDlgItemText(IDC_EdtErrorShow,(LPCTSTR)LocalLock(hLocal));
????????????? LocalFree(hLocal);
?????? }else
????????????? SetDlgItemText(IDC_EdtErrorShow,TEXT("Error Number not found!"));
}
?
????????????????????? 如非? 2008-11-22
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的对程序错误的处理——Windows核心编程学习手札之一的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unicode——Windows核心编程
- 下一篇: 进程——Windows核心编程学习手札系