Windows via C/C++ Part 1: Required Reading - Chapter1 错误处理

  [有删减]

  在开始接触Microsoft Windows提供的诸多特色之前,了解各个Windows函数如何进行错误处理是非常必要的。Windows函数在被调用时,会检查调用者提供的参数的有效性然后开始执行。当参数无效或是由于别的原因使函数无法正常执行时,函数的返回值会以错误码的形式告诉我们导致调用失败的原因。下面描述了大多数Windows函数的返回值类型。

  • VOID: 函数调用不可能失败。Windows API中只有一小部分函数的返回值为VOID。
  • BOOL:函数调用失败时,返回0;否则返回值为非0。
  • HANDLE:函数调用失败时,通常返回NULL;否则返回对象的句柄。有些函数返回INVALID_HANDLE_VALUE(-1)而不是NULL表示函数调用失败,此时应该查阅Platform SDK文档以获得准确信息。

PVOID:函数调用失败时,返回值为NULL,否则,返回指向数据块的指针。

  • LONG/DWORD:返回LONG/DWORD的函数调用比较繁杂,可以查阅函数的Platform SDK文档获得准确信息。

  理解API调用失败的错误码是很有用的,Microsoft预定义了API调用产生的可能的错误码,这些32位的错误码在WinError.h头文件中定义,比如:


 

  // MessageId: ERROR_FILE_NOT_FOUND
  //
  // MessageText:
  //
  // The system cannot find the file specified.
  //
  #define ERROR_FILE_NOT_FOUND             2L

 

 


 

 

  当Windows函数调用检测到错误发生时,函数使用“线程局部存储”机制将错误码和当前调用线程联系起来。“线程局部存储”允许各个线程相互独立运行而不至于影响到彼此的错误码。函数返回错误码后,可以调用GetLastError获取上次失败调用的准确错误码:

  DWORD GetLastError(); 

  接下来我们可以将GetLastError的返回值转换成更有用的信息,注意在WinError.h文件中,每个错误码除了32位的MessageID,还有与之对应的MessageText,后者对错误码进行了更详细的描述。在Visual Studio 2005及其后续版中以Bebug模式调试程序时,可以在变量监视窗口手动增加一行:$err,hr 显示当前线程的最后一次函数调用所产生的错误码(MessageID)和对应的文本描述(Message Text)。此外,Visual Studio自带的Error Lookup小工具也可以根据MessageID的值来显示相应的MessageText。 

  有时候程序需要将GetLastError返回值的文本描述缓存在数据块中,这正是FormatMessage函数的作用,它的声明如下: 

     

  FormatMessage的功能十分强大,一个原因得益于它对多语言的支持非常到位,只需要为其指定dwLanguageId参数,并在相应的dll或exe中嵌入错误码表,FormatMessage会自动选择相应语言的文本描述。接下来我们将举例说明FormatMessage的用法。

 

  [以下内容用于说明FormatMessage用法,并非原文翻译]

 

  FormatMessage的具体用法可以查阅MSDN,这里只做简要介绍,并覆盖原文的知识点。在介绍FormatMessage的其它参数之前,我们必须了解dwLanguageId的意义。dwLanguageId称为语言标识符(Language Identifiers),它以16位的数值形式描述某个国家或地区所使用的语言。每一种语言拥有唯一的语言标识符,包括主要语言标识符(primary language identifier)和子语言标识符(sublanguage identifier),语言标识符的组成如下所示:

+-----------------------------+-------------------------------+
|     SubLanguage ID        |   Primary Language ID    |
+-----------------------------+-------------------------------+
15                               10  9                              0   bit

  Windows已预义了可能出现的主要语言标识符和子语言标识符,比如简体中文的主要语言标识符为:LANG_CHINESE_SIMPLIFIED,其子语言标识符为SUBLANG_CHINESE_SIMPLIFIED,美国英语的主要语言标识符为:LANG_ENGLISH,其子语言标识符为SUBLANG_ENGLISH_US。以主要/子语言标识符做宏MAKELANGID的参数,既可得到相应的语言标识符,如: 

    

  除了使用MAKELANGID生成语言标识符外,Windows预定义了几种语言标识符,如LANG_SYSTEM_DEFAULT和LANG_USER_DEFAULT分别表示操作系统默认语言和当前用户语言。  

  参数dwFlags在调用FormatMessage获取Windows预定义的错误码文本描述信息时,通常包含FORMAT_MESSAGE_FROM_SYSTEM、FORMAT_MESSAGE_IGNORE_INSERTS,前者指明函数将搜索系统字符串资源表,后者表示如果dwError指定的错误码描述存在且其中含有转义字符序列,则忽略这些转义字符并将描述信息完整拷贝到lpBuffer中,否则将使用Arguments参数填充转义序列。dwFlags还可以包含FORMAT_MESSAGE_ALLOCATE_BUFFER,表示lpBuffer所需的内存将由FormatMessage自身分配(通过调用LocalAlloc),此时在lpBuffer使用完之后应该手动调用LocalFree释放内存。参数lpSource和Arguments在获取Windows预定义的错误码描述信息时常将其忽略,nSize用于在用户手动分配lpBuffer内存时指明其大小,或dwFlags包含FORMAT_MESSAGE_ALLOCATE_BUFFER时指示FormatMessage为lpBuffer分配的最小内存大小。 

  下面是两个使用FormatMessage获得Windows预定义错误码描述信息的例子,我们设置dwError为11,表示“试图加载格式不正确的程序”: 

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值