程序员 必读

     对程序错误的处理在开始介绍Microsoft Windows 的特性之前,必须首先了解Wi n d o w s的各个函数是如何进行错误处理的。当调用一个Wi n d o w s函数时,它首先要检验传递给它的的各个参数的有效性,然后再设法执行任务。如果传递了一个无效参数,或者由于某种原因无法执行这项操作,那么操作系统就会返回一个值,指明该函数在某种程度上运行失败了。表 1 - 1列出了大多数Wi n d o w s函数使用的返回值的数据类型。表1-1 Wi n d o w s函数常用的返回值类型数 据 类 型 表示失败的值V O I D 该函数的运行不可能失败。Wi n d o w s函数的返回值类型很少是V O I DB O O L 如果函数运行失败,那么返回值是0,否则返回的是非0值。最好对返回值进行测试,以确定它是0还是非0。不要测试返回值是否为T R U EH A N D L E 如果函数运行失败,则返回值通常是N U L L,否则返回值为H A N D L E,用于标识你可以操作的一个对象。注意,有些函数会返回一个句柄值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 DP 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公司编译了一个所有可能的错误代码的列表,并且为每个错误代码分配了一个 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函数:该函数只返回线程的3 2位错误代码。当你拥有3 2位错误代码的号码时,必须将该号码转换成更有用的某种对象。 Wi n E r r o r. h头文件包含了M i c r o s o f t公司定义的错误代码的列表。下面显示了该列表的某些内容,使你能够看到它的大概样子:

免使用这个号码,可使用消息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之类的函数来报告错误,而且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 nt函数的例子。进行调试的时候,监控线程的最后错误代码是非常有用的。在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所指的字符串是相同的。图1-1 在Visual Studio 6.0的Wa t c h窗口中键入“@ e r r, h r”,就可以查看当前线程的最后错误代码F o r m a t M e s s a g e函数的功能实际上是非常丰富的,在创建向用户显示的字符串信息时,它是首选函数。该函数之所以有这样大的作用,原因之一是它很容易用多种语言进行操作。该函数能够检测出用户首选的语言(在Regional Settings Control Panel小应用程序中设定),并返回相应的文本。当然,首先必须自己转换字符串,然后将已转换的消息表资源嵌入你的 . e x e文件或D L L模块中,然后该函数会选定正确的嵌入对象。 E r r o r S h o w示例应用程序(本章后面将加以介绍)展示了如何调用该函数,以便将M i c r o s o f t公司定义的错误代码转换成它的文本描述。有些人常常问我,M i c r o s o f t公司是否建立了一个主控列表,以显示每个Wi n d o w s函数可能返回的所有错误代码。可惜,回答是没有这样的列表,而且 M i c r o s o f t公司将永远不会建立这样的一个列表。因为在创建系统的新版本时,建立和维护该列表实在太困难了。建立这样一个列表存在的问题是,你可以调用一个 Wi n d o w s函数,但是该函数能够在内部调用另一个函数,而这另一个函数又可以调用另一个函数,如此类推。由于各种不同的原因,这些函数中的任何一个函数都可能运行失败。有时,当一个函数运行失败时,较高级的函数对它进行恢复,并且仍然可以执行你想执行的操作。为了创建该主控列表, M i c r o s o f t公司必须跟踪每个函数的运行路径,并建立所有可能的错误代码的列表。这项工作很困难。而且,当创建系统的新版本时,这些函数的运行路径还会改变。1.1 定义自己的错误代码前面已经说明 Wi n d o w s函数是如何向函数的调用者指明发生的错误,你也能够将该机制用于自己的函数。比如说,你编写了一个希望其他人调用的函数,你的函数可能因为这样或那样的原因而运行失败,你必须向函数的调用者说明它已经运行失败。若要指明函数运行失败,只需要设定线程的最后的错误代码,然后让你的函数返回FA L S E、I N VA L I D _ H A N D L E _ VA L U E、N U L L或者返回任何合适的信息。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容

  • 一年级语文上册生字表 生字表一(共400字) 啊(ā)爱(ài)安(ān)岸(àn)爸(bà)八(bā)巴(bā)...
    meychang阅读 2,791评论 0 6
  • sì 支zhī茶chá 对duì 酒jiǔ,赋fù 对duì 诗shī,燕yàn子zi 对duì 莺yīng 儿é...
    每个人的孟母堂阅读 1,209评论 0 6
  • 1. 关于诊断X线机准直器的作用,错误的是()。 (6.0 分) A. 显示照射野 B. 显示中心线 C. 屏蔽多...
    我们村我最帅阅读 10,384评论 0 5
  • 网上众多教程针对Windows,幸运地在逼乎上看到了一篇回答(已感谢答主:单芸峰)。 一 下载pip (Pytho...
    toedwy阅读 3,039评论 3 7
  • 老人们常说的老话儿:“病由心生”。不生气就不会生病。真的,其实很多病都是自己作的,大多数疾病都和生气有关,不生气就...
    简书粉粉阅读 1,351评论 0 1