译文
第一章
错误外理
在我们着手开始探索微软操作系(简称Windows)所提供的许多功能时,你需要理解各种系统函数(API)是如何进行错误处理的。
当你调用一个函数时,调函数首先会对你传给它的参数进行认证,然后才执行。如果存在无郊参数或者由于某种原因该函数不能被执行,那么函数就会返回一个表明该函数调用失败的原因。表1-----1是大部分函数使用的返回数据类型。
数据类型 |
值的意义 |
VOID |
这种类型不是说明函数调用失败。很少函数返回这种类型 |
BOOL |
如果函数失败就会返回0;否则就返回非零值。检查返回值是否为零是比较实用的,不用检查返回值是真还是假。(但我个人不这样认为) |
HANDLE |
如果函数失败,返回值是非NULL;否则返回值是指向一个你可以使用的句柄(我从不称句柄,但我不明前人为什么要这样翻译,我称HANDLE为操作对象);要注意它的返回值是不是常量INVALID_HANDLE_VALUE=-1,SDK软件开发工具的相关文档给这些函数明确指出它们的返回值是NULL还是INVALD_HANDLE_VALUE,这两个返回值的意译是不一样的,都说明函数失败。 |
PVOID |
如果函数失败,返回值是NULL;否则返回的是识别一个数据块的内存地址(我不太理解,POVID是可以指向任何类型的指针,为什么会出现这种情况) |
LONG/DWORD |
这是一个难点,(我也同意这点,我看不太明Functions that return counts usually return a LONG or DWORD)。如果由于某种原因函数不能计算想要计算的东西,那么就会返回0或-1(取决于函数本身)。如果调用了一个返回值为LONG或DWARD类型的,请仔细阅读SDK里的相关文档,保证确切的找到它隐含的错误。 |
当函数返回一个错误代号时,人们总是利用它来确定函数为什么会失败。微软已经为所有可能会出现的错误列了一分表并且为每一个错误都分配一个32位数值的代号。
当函数检测到一个错误时,它就使用一个称为本地线程存贮的内部结构来联系相应的错误代号,通过调用一个线程。(TLS将会在第21章讨论)。这种机构使得线程可以独自运行,不会影响其它线程的错误号。(When the function returns to you, its return value will indicate that an error has occurred. To see exactly which error this is, call the GetLastError function:这句写得不是很确切)如果函数有错误,返回值就表明有错误产生。通过调用GetLastError()可以找到是什么错误。
DWORD GetLastError(); |
这个函数只返回这个线程找到的一个32位错误码。
既然知道了这么一个错误码,你就得把它转译成相应的能看懂的文本信息。WinError.h这个头文件就罗列了由微软定义的所有错误码的意义。我再次列出了一些,让你看看它是什么样的。
#define ERROR_SUCCESS 0L #define NO_ERROR 0L #define SEC_E_OK ((HRESULT)0x00000000L) #define ERROR_INVALID_FUNCTION 1L #define ERROR_FILE_NOT_FOUND 2L #define ERROR_PATH_NOT_FOUND 3L #define ERROR_TOO_MANY_OPEN_FILES 4L #define ERROR_ACCESS_DENIED 5L |
你可以看到,每一个错误码都有三部分组成:消息ID(它是一个宏,你可以在编程时使用它来与GetLastError()的返回值比较,进而作相应的外理);消息内容(是有英文写的错误码描述),一个数字(不要使用它,而要使用消息ID)。记住,我只是列出了WinError.h 头文件的一部分,整个头文件超过21000行。
如果函数不成功,得接着就调用GetLastError()否则这个错误码可能会被其它函数的错误码所覆盖。
注:
GetLastError 只返回线程最后产生的错误码。如果一个线程调用成功一个函数,那么上次的错误码不会被覆盖,也不会表明该函数调用成功。但是有一些函数不会按这个规则进行,它们会改变错误码;(however, the Platform SDK documentation usually indicates that the function changes the last error code when the function succeeds.“the function ”代指什么?)