初窥Windows---错误处理

一、常见错误

调用windows函数时,会先验证参数,在开始执行任务,如果参数传入错误,或者由于其他原因导致操作无法执行,则函数的返回值将指出函数函数因为哪些原因失败,大多数的返回值类型

   数据类型                                  指出函数调用失败的原因
      VOID

这个函数不可能失败。只有极少数的函数的返回值是void

      BOOL失败返回0;否则返回非0值。在使用时应避免测试返回值是否为true;应该去判断返回值是否是FALSE
    HANDLE失败NULL;否则,HANDLE将标识一个可操作的对象,其中当返回值是INVALID_HANDLE_VALUE(-1)这个句柄时也是失败的,但是NULL与它所代表的的含义完全不同
     PVOID失败NULL;否则,PVOID 将标识一个数据块的内存地址
LONG/DWORD返回计数器的函数通常会返回一个LONG或DWORD。如果函数因为某种原因不能对我们想要记数的东西进行计数,他通常会返回0或-1

自己以后设计函数时一定要对返回值进行慎用,尤其是返回值为void的函数,代表该函数不会出错。

二、错误代码

microsoft有一个列表,其中列出了所有可能的函数返回的错误代码,并且为每个代码分配了一个32位的编号。

机制: 当windows函数检测到错误时,它会使用一种名为“线程本地存储区”的机制将相应的错误代码与“主调线程”关联到一起,使得不同的线程能独立运行,不会相互干扰对方的错误代码,且函数返回错误时,会返回一个已经发生了的错误代码,使用GetLastError()可以查看具体错误。

DWORD GetLastError()     //返回由上一个函数调用设置的线程的32位错误代码

当windows函数调用失败之后应当立刻调用GetLastError,因为假如又调用了另一个windows函数,则此时GetLastError函数的返回值可能会被改写。如果windows函数调用成功,返回值可能会变为ERROR_SUCCESS.

为什么要采用GetLastError?

Windows函数调用成功的原因是不同的,例如,创建一个具名事件内核对象时,以下两种情况都会成功:对象实际完成创建,或存在一个同名的事件内核对象。应用程序或许知道这些原因,为捕捉到具体的返回信息,Microsoft采用“上一个错误代码”机制,所以当特定函数调用成功时,可以使用GetLastError函数来获取确定的额外的信息。例如:CreateEvent函数,如果已经存在具名事件,就返回ERROR_ALREAD_EXISTS。

windows 32位的错误代码定义列表在 WinError.h头文件之中。下面摘录部分

//
// MessageId: ERROR_INVALID_FUNCTION
//
// MessageText:
//
// Incorrect function.
//
#define ERROR_INVALID_FUNCTION           1L    // dderror

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

//
// MessageId: ERROR_PATH_NOT_FOUND
//
// MessageText:
//
// The system cannot find the path specified.
//
#define ERROR_PATH_NOT_FOUND             3L

三、错误代码的表示

右上面所摘录的部分WinError.h头文件的内容可以看出,一个错误有三种表示:一个消息ID(可以在资源代码中使用的宏,用于与GetLastError的返回值进行对比)、消息文本(描述错误的具体内容的英文文本)、一个编号(不要使用此编号,使用ID)

Windows中有一个函数,可以将错误代码转换为相应的文本描述。此函数为FormatMessage

DWORD FormatMessage(
    _In_     DWORD dwFlags,
    _In_opt_ LPCVOID lpSource,
    _In_     DWORD dwMessageId,
    _In_     DWORD dwLanguageId,
    _Out_    LPWSTR lpBuffer,
    _In_     DWORD nSize,
    _In_opt_ va_list *Arguments);

该函数的具体使用方式以及各个参数的详细解释:FormatMessage    FormatMessage函数的用法

FormatMessage的功能十分丰富,用来格式化消息字符串,就是处理消息资源的。它可以支持多种语言(自然语言,汉语,英语等)。它能获取一个语言标识作为参数,并返回那种语言的文本,当然,我们必须先翻译字符串,并将翻译好的消息表资源嵌入自己的.exe或dll模块之中。

四、定义自己的错误代码

Microsoft允许我们将Windows函数如何向其调用者指出错误这种机制使用于我么自己的函数中,假定我们要写一个供其他人调用的函数。这个函数可能会因为某些原因失败,所以需要向调用者指出错误。

为了指出错误,只需要设置线程的上一个错误代码,然后令自己的函数返回FALSE,INVALID_HANDLE_VALUE、NULL或者其他适合的值。为了设置线程的上一个错误代码,只需要调用以下函数,并传递我们认为合适的任何32位的值:

VOID SetLastError(_In_ DWORD dwErrCode);

五、错误代码的字段组成

错误代码是一个32位的数,下表描述了错误代码的几个不同字段所代表的的不同含义

   位      31-30               29     28   27-16      15-0
  内容      严重性           Microsoft    Facility    异常代码
  含义

   0 = 成功

   1 = 信息(提示)

   2 = 警告

   3 = 错误

 0 = Microsoft 定义的代码

 1 = 客户定义的代码

必须为 0前256个值由Microsoft保留Microsoft / 客户定义的代码

29位的存在可以保证我们的错误代码绝对不会与Microsoft现在和将来定义的错误代码冲突。Facility字段非常大,足以容纳4096个可能的值,其中前256个是Microsoft保留的,其余的值可由自己来定义。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值