Windows编程中的错误处理


Windows编程中的错误处理
2010年07月09日
  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); void WINAPI SetLastError( __in DWORD dwErrCode); void WINAPI SetLastErrorEx(__in DWORD dwErrCode, DWORD dwType); DWORD WINAPI FormatMessage( __in DWORD dwFlags, __in LPCVOID lpSource, __in DWORD dwMessageId, __in DWORD dwLanguageId, __out LPTSTR lpBuffer, __in DWORD nSize, __in va_list* Arguments); DWORD WINAPI GetLastError(void);,他的作用是获取由系统API产生的错误代码,代码的详细信息可参考MSDN或是微软公布的错误代码获取API的错误信息,   当然,我们也可以直接让他显示出错误信息,如何操作呢,这就用到下面的函数
  DWORD WINAPI FormatMessage( __in DWORD dwFlags, //指定格式化程序以及解释lpsource参数的方法 __in LPCVOID lpSource, //消息定义指针 __in DWORD dwMessageId, //为要求消息指定32位信息标识符 __in DWORD dwLanguageId, //不支持 __out LPTSTR lpBuffer, //指向一个格式化消息的缓冲区 __in DWORD nSize, //指定输出缓冲区大小 __in va_list* Arguments //指向在格式化消息中被用来插入数值的一个32位数值的数组 );  具体信息可参看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可能出错的地方,他将给你提示出你的函数错误的描述信息。 DWORD dwErrCode 就是你想要设置的错误代码,不过要注意的是,你的错误代码不能和系统冲突,下面是系统已经定义的错误代码字段信息:  对于这两个函数的具体使用和这些字段的用法,请看下集故事:windows编程中的异常处理和windows结构化异常处理方式解析。

猜你喜欢

转载自ugotd61y.iteye.com/blog/1362967