Windows编程——错误处理


前言

在深入讨论Microsoft Windows提供的诸多特性之前,应该先理解各个Windows函数是如何进行错误处理的。这一篇文章主要讲述怎样定义自己的错误代码。


一、错误的发生,以及常见的错误

调用Windows函数时,它会先验证我们传给他的参数,然后开始执行任务。如果传入的参数无效,或者由于其它原因导致操作无法执行,则函数的返回值将指出函数因为某些原因失败了。
常见的Windows函数返回值数据类型:

  1. VOID:这个函数不可能失败。
  2. BOOL:如果函数失败,返回值为0,否则返回一个非0值
  3. HANDLE:如果函数失败,则返回值通常为NULL,否则,HANDLE将标识一个可以操纵的对象。
  4. PVOID:如果函数调用失败,则返回值为NULL;否则,PVOID将标识一个数据库的内存地址。
  5. LONG/DWORD:这种类型比较棘手,暂不讨论。

通常情况下,如果WIndows函数能返回错误代码,将有助于我们理解函数调用为啥会失败。为此,Microsoft编辑了一个列表,其中列出了所有可能的错误代码,并为每个错误代码部分都分配了一个32位的编号。
在内部,当WIndows函数检测到错误时,它会使用一种名为线程本地存储区 thread-local-storage的机制将相应的错误代码与主调线程关联在一起(线程本地存储后面的文章讨论)。这种机制使不同的线程能独立运行,不会出现相互干扰对方的错误代码的情况。函数返回时,其返回值会指出一个易发生的错误,要查看是什么错误,请调用GetLastError()函数。如下所示:

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

有了32位错误代码后,可以在WinError.h头文件中查看Microsoft定义的错误代码列表。该头文件太多,无法全部展示。 下面是该头文件的部分代码:

#define NO_ERROR                                           0
#define ERROR_SUCCESS                                      0
#define ERROR_INVALID_FUNCTION                             1
#define ERROR_FILE_NOT_FOUND                               2
#define ERROR_PATH_NOT_FOUND                               3
#define ERROR_TOO_MANY_OPEN_FILES                          4
#define ERROR_ACCESS_DENIED                                5
#define ERROR_INVALID_HANDLE                               6
#define ERROR_ARENA_TRASHED                                7
#define ERROR_NOT_ENOUGH_MEMORY                            8
#define ERROR_INVALID_BLOCK                                9
#define ERROR_BAD_ENVIRONMENT                              10
#define ERROR_BAD_FORMAT                                   11
#define ERROR_INVALID_ACCESS                               12
#define ERROR_INVALID_DATA                                 13
#define ERROR_OUTOFMEMORY                                  14
#define ERROR_INVALID_DRIVE                                15
#define ERROR_CURRENT_DIRECTORY                            16
#define ERROR_NOT_SAME_DEVICE                              17
#define ERROR_NO_MORE_FILES                                18
#define ERROR_WRITE_PROTECT                                19
#define ERROR_BAD_UNIT                                     20
#define ERROR_NOT_READY                                    21
#define ERROR_BAD_COMMAND                                  22
#define ERROR_CRC                                          23
#define ERROR_BAD_LENGTH                                   24
#define ERROR_SEEK                                         25
#define ERROR_NOT_DOS_DISK                                 26
#define ERROR_SECTOR_NOT_FOUND                             27
#define ERROR_OUT_OF_PAPER                                 28
#define ERROR_WRITE_FAULT                                  29
#define ERROR_READ_FAULT                                   30
#define ERROR_GEN_FAILURE                                  31
#define ERROR_SHARING_VIOLATION                            32
#define ERROR_LOCK_VIOLATION                               33
#define ERROR_WRONG_DISK                                   34
#define ERROR_SHARING_BUFFER_EXCEEDED                      36
#define ERROR_HANDLE_EOF                                   38
#define ERROR_HANDLE_DISK_FULL                             39
#define ERROR_NOT_SUPPORTED                                50
#define ERROR_REM_NOT_LIST                                 51
#define ERROR_DUP_NAME                                     52
#define ERROR_BAD_NETPATH                                  53
#define ERROR_NETWORK_BUSY                                 54
#define ERROR_DEV_NOT_EXIST                                55
#define ERROR_TOO_MANY_CMDS                                56
#define ERROR_ADAP_HDW_ERR                                 57
#define ERROR_BAD_NET_RESP                                 58
#define ERROR_UNEXP_NET_ERR                                59
#define ERROR_BAD_REM_ADAP                                 60
#define ERROR_PRINTQ_FULL                                  61
#define ERROR_NO_SPOOL_SPACE                               62
#define ERROR_PRINT_CANCELLED                              63
#define ERROR_NETNAME_DELETED                              64
#define ERROR_NETWORK_ACCESS_DENIED                        65
#define ERROR_BAD_DEV_TYPE                                 66
#define ERROR_BAD_NET_NAME                                 67
#define ERROR_TOO_MANY_NAMES                               68
#define ERROR_TOO_MANY_SESS                                69
#define ERROR_SHARING_PAUSED                               70
#define ERROR_REQ_NOT_ACCEP                                71
#define ERROR_REDIR_PAUSED                                 72
#define ERROR_FILE_EXISTS                                  80
#define ERROR_CANNOT_MAKE                                  82
#define ERROR_FAIL_I24                                     83
#define ERROR_OUT_OF_STRUCTURES                            84
#define ERROR_ALREADY_ASSIGNED                             85
#define ERROR_INVALID_PASSWORD                             86
#define ERROR_INVALID_PARAMETER                            87
#define ERROR_NET_WRITE_FAULT                              88
#define ERROR_NO_PROC_SLOTS                                89
#define ERROR_TOO_MANY_SEMAPHORES                          100
#define ERROR_EXCL_SEM_ALREADY_OWNED                       101
#define ERROR_SEM_IS_SET                                   102
#define ERROR_TOO_MANY_SEM_REQUESTS                        103
#define ERROR_INVALID_AT_INTERRUPT_TIME                    104
#define ERROR_SEM_OWNER_DIED                               105

要查看WinError.h,请到该网站:WinError.h
函数调用失败之后,应该立马使用GetLastError,否则会被下一个Windows函数的结果改写。注意,成功的调用可能会将该值改写为ERROR_SUCCESS。

二、定义自己的错误代码

前面说了Windows函数如何向其调用者指出错误,MicroSoft还允许将这种机制用于我们自己的函数中。假定我们要写一个供他人调用的函数,这个函数可能会因为某些原因调用失败,所以我们需要向他的调用者指出错误。
为了指出错误,需要设置线程上的一个错误代码,然后令自己的函数返回FALSE,INVALID_HANDLE_VALUE,NULL或者其它合适的值。
为了设置线程的上一个错误代码,只需要调用以下代码,并传递我们认为合适的任何32位值:

VOID SetLastError(DWORD dwErrCode);

错误代码的不同字段:

  1. 31-30:严重性:0为成功,1为提示,2为警告,3为错误
  2. 29:Microsoft/客户:0为Microsoft定义的代码,1为客户定义的代码
  3. 28:保留:必须为0
  4. 27-16:前256个值由Microsoft保留
  5. 15-0:异常代码:Microsoft/客户定义的代码
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BabyOne~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值