Windows編程中的錯誤處理

來源:互聯網
上載者:User

Windows編程中獲得錯誤資訊

在windows編程中我們的函數往往不如我們想象的那樣工作,他經常會出現很多這樣那樣的問題,一般情況下,我們可以通過他們的傳回值來得到他們到底是否發了小脾氣:

Windows常見的傳回值類 型:
1) VOID:表明該函數運行不可能失敗,Windows函 數的傳回值很少是VOID。
2) BOOL:如果函數運行失敗,傳回值是0,否則 傳回值是非0值。最好對傳回值進行測試,以確定它是0還 是非0,而不是測試傳回值是否是TRUE。
3) HANDLE:如果函數運行失敗,則傳回值通常是NULL, 否則傳回值是某個HANDLE,用於標識你可以操作的一個對象。請注意這些值,有些函數失敗時會返回一個控制代碼值INVALID_HANDLE_VALUE, 它被定義為-1。函數的Platform SDK文 檔將會清楚地說明函數運行失敗時傳回值是NULL還是INVALID_HANDLE_VALUE。
4) PVOID:如果函數運行失敗,傳回值是NULL, 否則返回PVOID,以標識資料區塊的記憶體位址。
5) LONG/DWORD:這是個難以處理的值。返回數量的函數通常返回LONG或DWORD,如果由於某種原因,函數無法對想要進行計數的對象進行計數,那麼該函數通常返回0或-1(根據函數而定)。如果調用的函數傳回值為LONG或DWORD,那麼得閱讀Platform SDK以確保能正確檢測潛在的錯誤。

由此可見,得到錯誤資訊對我們修改程式協助很大,如何擷取這些錯誤資訊呢。其實非常簡單,windows為我們提供了3個API函數,我們可以使用他們來擷取錯誤資訊。

DWORD WINAPI GetLastError(void);<br />void WINAPI SetLastError( __in DWORD dwErrCode);<br />void WINAPI SetLastErrorEx(__in DWORD dwErrCode,<br />DWORD dwType);<br />DWORD WINAPI FormatMessage(<br />__in DWORD dwFlags,<br /> __in LPCVOID lpSource,<br /> __in DWORD dwMessageId,<br />__in DWORD dwLanguageId,<br />__out LPTSTR lpBuffer,<br />__in DWORD nSize,<br />__in va_list* Arguments);

DWORD WINAPI GetLastError(void);,他的作用是擷取由系統API產生的錯誤碼,代碼的詳細資料可參考MSDN或是微軟公布的錯誤碼擷取API的錯誤資訊,
   當然,我們也可以直接讓他顯示出錯誤資訊,如何操作呢,這就用到下面的函數

DWORD WINAPI FormatMessage(<br /> __in DWORD dwFlags, //指定格式化程式以及解釋lpsource參數的方法<br />__in LPCVOID lpSource, //訊息定義指標<br />__in DWORD dwMessageId, //為要求訊息指定32位資訊標識符<br />__in DWORD dwLanguageId, //不支援<br /> __out LPTSTR lpBuffer, //指向一個格式化訊息的緩衝區<br />__in DWORD nSize, //指定輸出緩衝區大小<br />__in va_list* Arguments //指向在格式化訊息中被用來插入數值的一個32位元值的數組<br />);

 具體資訊可參看MSDN.

上對他的說明這裡我們使用一個簡單的例子來說明他們的用法:
int a = GetDlgItemInt(IDC_EDIT4);int b = GetDlgItemInt(IDC_EDIT5);typedef int(_stdcall *lpAddFun)(int, int);HINSTANCE hDll;hDll = LoadLibrary(_T("Dll2.dll"));lpAddFun AddFun = (lpAddFun)GetProcAddress(hDll, "Subtract");if (AddFun != NULL){int c = AddFun(a, b);SetDlgItemInt(IDC_EDIT6,c);}else{LPVOID lpMsgBuf;LPVOID lpDisplayBuf;DWORD dw = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,NULL,dw,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0, NULL );lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+40)*sizeof(TCHAR)); StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf),TEXT("failed with error %d: %s"), dw, lpMsgBuf); ::MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf);LocalFree(lpDisplayBuf);}FreeLibrary(hDll);

 

這裡是動態載入DLL,如果成功,後面代碼將正確執行,如果錯誤,將返回錯誤資訊的詳細說明。其中,後面一部分代碼可以直接使用,把他加入你的代碼調用API可能出錯的地方,他將給你提示出你的函數錯誤的描述資訊。

假設我們想要在自己代碼中自訂錯誤資訊,這是允許的,你可以使用

void WINAPI SetLastError( __in DWORD dwErrCode);<br />void WINAPI SetLastErrorEx( __in DWORD dwErrCode, DWORD dwType);
 

 

DWORD dwErrCode 就是你想要設定的錯誤碼,不過要注意的是,你的錯誤碼不能和系統衝突,下面是系統已經定義的錯誤碼欄位資訊:

31~30

29

28

27~16

15~0

內容

嚴重性

Microsoft/客戶

保留

Facility代碼

異常代碼

含義

0=成功

1=供參考

2=警告

3=錯誤

0=Microsoft定義的代碼

1=客戶定義的代碼

必須是0

前256個值由Microsoft保留

Microsoft/客戶定義的代碼

對於這兩個函數的具體使用和這些欄位的用法,請看下集故事:windows編程中的異常處理和windows結構化異常處理方式解析。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.