WINDOWS核心编程(一)

在开始介绍Microsoft Windows 的特性之前,必须首先了解Windows的各个函数是如何进行错误处理的。

当调用一个Windows函数时f.i.r飞行部落

,它首先要检验传递给它的的各个参数的有效性,然后再设法执行任务。如果传递了一个无效参数,或者由于某种原因无法执行这项操作,那么操作系统就会返回一个值,指明该函数在某种程度上运行失败了。表1 - 1列出了大多数Windows函数使用的返回值的数据类型。

表1-1 Wi n d o w s 函数常用的返回值类型

数据类型

表示失败的值

V O I D

该函数的运行不可能失败。Wi n d o w s 函数的返回值类型很少是V O I D

B O O L

如果函数运行失败,那么返回值是0 ,否则返回的是非0 值。最好对返回值进行测试,以确定它是0 还是非0 。不要测试返回值是否为T R U E

H A N D L E

如果函数运行失败,则返回值通常是N U L L ,否则返回值为H A N D L E ,用于标识你可以操作的一个对象。注意f.i.r 现场版,有些函数会返回一个句柄值I N VALID_ HANDLE_VA L U E ,它被定义为- 1 。函数的Platform SDK 文档将会清楚地说明该函数运行失败时返回的是N U L L 还是I N VA L I D _ H A N D L E _ VA L I D

P V O I D

如果函数运行失败,则返回值是N U L L ,否则返回P V O I D ,以标识数据块的内存地址

L O N G / D W O R D

这是个难以处理的值。返回数量的函数通常返回L O N G 或D W O R D 。如果由于某种原因,函数无法对想要进行计数的对象进行计数,那么该函数通常返回0 或- 1 (根据函数而定)。如果调用的函数返回了L O N G / D W O R D ,那么请认真阅读Platform SDK文档,以确保能正确检查潜在的错误

一个Wi n d o w s 函数返回的错误代码对了解该函数为什么会运行失败常常很有用。M i c r o s o f t公司编译了一个所有可能的错误代码的列表f.i.r 三个愿望 mp3,并且为每个错误代码分配了一个3 2 位的号码。

从系统内部来讲,当一个Wi n d o w s 函数检测到一个错误时,它会使用一个称为线程本地存储器(thread-local storage )的机制,将相应的错误代码号码 与调用的线程关联起来(线程本地存储器将在第2 1 章中介绍)。这将使线程能够互相独立地运行,而不会影响各自的错误代码。当函数返回时,它的返回值 就能指明一个错误已经发生。若要确定这是个什么错误,请调用G e t L a s t E r r o r 函数:

DWORD GetLastError();

该函数只返回线程的3 2 位错误代码。

当你拥有3 2 位错误代码的号码时,必须将该号码转换成更有用的某种对象。Wi n E r r o r. h 头文件包含了M i c r o s o f t 公司定义的错误代码的列 表。下面显示了该列表的某些内容,使你能够看到它的大概样子:

// MessageId: ERROR_SUCCESS // // MessageText: // // The operation completed successfully. // #define ERROR_SUCCESS 0L #define NO_ERROR 0L // dderror // // 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 // // MessageId: ERROR_TOO_MANY_OPEN_FILES // // MessageText: // // The system cannot open the file. // #define ERROR_TOO_MANY_OPEN_FILES 4L // // MessageId: ERROR_ACCESS_DENIED // // MessageText: // // Access is denied. // #define ERROR_ACCESS_DENIED 5L

如你所见f.i.r爱过mtv,每个错误都有3 种表示法:一个消息I D (这是你可以在源代码中使用的一个宏,以便与G e t L a s t E r r o r 的返回值进行比较),消息文本(对错误的英文描述)和一个号码(应该避免使用这个号码,可使用消息I D )。请记住,这里只显示了Wi n E r r o r. h 头文件中的很少一部分内容,整个文件的长度超过2 1 0 0 0 行。

当Wi n d o w s 函数运行失败时,应该立即调用G e t L a s t E r r o r 函数。如果调用另一个Wi n d o w s 函数,它的值很可能被改写。

注意G e t L a s t E r r o r 能返回线程产生的最后一个错误。如果该线程调用的Wi n d o w s 函数运行成功,那么最后一个错误代码就不被改写,并且不指明运行成功。有少数Wi n d o w s 函数并不遵循这一规则,它会更改最后的错误代码;但是Platform SDK 文档通常指明,当函数运行成功时,该函数会更改最后的错误代码。

Wi n d o w s 9 8 许多Windows 98 的函数实际上是用M i c r o s o f t 公司的1 6 位Windows 3.1 产品产生的1 6 位代码来实现的。这种比较老的代码并 不通过G e t L a s t E r r o r 之类的函数来报告错误

音乐咖啡屋-千里之外舞笑嘻嘻吓你一跳!!!(6秒种)吓你一跳!!!九只狐狸~~
f.i.r成员名字,而且M i c r o s o f t 公司并没有在Windows 98 中修改1 6 位代码,以支持这种错误处理方式 。对于我们来说,这意味着Windows 98 中的许多Wi n 3 2 函数在运行失败时不能设置最后的错误代码。该函数将返回一个值,指明运行失败,这样你就能够 发现该函数确实已经运行失败,但是你无法确定运行失败的原因。

有些Wi n d o w s 函数之所以能够成功运行,其中有许多原因。例如,创建指明的事件内核对象之所以能够取得成功,是因为你实际上创建了该对象,或者因为已经存在带有相同名字的事件内核对象。你应搞清楚成功的原因。为了将该信息返回,M i c r o s o f t 公司选择使用最后错误代码机制。这样,当某些函数运行成功时,就能够通过调用G e t L a d t E r r o r 函数来确定其他的一些信息。对于具有这种行为特性的函数来说,Platform SDK 文档清楚地说明了G e t L a s t E r r o r 函数可以这样使用。请参见该文档,找出C r e a t e E v e n t 函数的例子。

进行调试的时候,监控线程的最后错误代码是非常有用的。在Microsoft Visual studio 6.0 中,M i c r o s o f t 的调试程序支持一个非常有用的特性,即可以配置Wa t c h 窗口,以便始终都能显示线程的最后错误代码的号码和该错误的英文描述。通过选定Wa t c h 窗口中的一行,并键入“@ e r r, h r ”,就能够做到这一点。观察图1 - 1 ,你会看到已经调用了C r e a t e F i l e 函数。该函数返回I N VA L I D _ H A N D L E _ VA L U E (- 1 )的H A N D L E ,表示它未能打开指定的文件。但是Wa t c h 窗口向我们显示最后错误代码(即如果调用G e t L a s t E r r o r 函数,该函数返回的错误代码)是0 x 0 0 0 0 0 0 0 2 。该Wa t c h 窗口又进一步指明错误代码2 是指“系统不能找到指定的文件。”你会发现它与Wi n E r r o r. h 头文件中的错误代码2 所指的字符串是相同的。


>>>QQ470681378

推荐阅读☆☆☆☆☆

Free Web Hosting  ---  Free Hit Counter