Larry Osterman系列--不要把话说得太满
2022-1-8 07:54:41 Author: mp.weixin.qq.com(查看原文) 阅读量:7 收藏

Erroneous assumptions - [2004-04-05]

有人可能注意过,几乎所有Win32 API文档对返回值的描述类似这样

成功时返回NO_ERROR,失败时返回下列错误码之一

ERROR_INVALID_PARAMETER (关于无效参数的描述)
Other                   (参看WinError.h)

无法想像有多少人抱怨过上述对返回值的描述,微软究竟为啥不能在文档中直接枚举所有错误码?他们是傻,还是不聪明呢?

其实答案很简单,过去我们被坑过,我们不想再被坑一把。我桌上的纪念品中有本MS-DOS 2.0参考手册,微软于1984年出版。在第1-143页,有个创建句柄的API,这是DOS版的open()函数。该API文档枚举了当时所有的错误码

AX可取值有

3 = 找不到路径
4 = 打开的文件太多
5 = 拒绝访问

微软和IBM公布了所有DOS调用的所有返回值信息,我们跟客户说,INT 21的0x3D号调用只有三种返回值(3、4、5)。你知道吗,客户相信我们,他们基于这个说法开发应用程序。

好吧,随之而来的是DOS 3.1,它增加了对网络的支持,于是新增了一些失败原因,比如,"未找到网络路径"(文件在服务器上但服务器下线了),"共享冲突"(有人以排他方式打开了一个共享文件,导致他人打开失败)。

起初DOS 3.1通过AX返回新的错误码。微软以为绝大多数程序员足够聪明,知道将来会出现3、4、5之外的新的错误码。我们开始测试DOS 3.1的兼容性,发现这个假设大错特错。已有的应用程序左崩崩、右崩崩,每个被测应用都崩了。为啥?因为微软和IBM告诉这些应用的开发者,他们只会得到3、4、5三种错误码。当年内存非常昂贵,他们不想编写容错性更强的代码,那样太费内存。当你的应用跑在64KB内存的主机上时,容错性只是可选项。

为了保持向后兼容性,微软只好为DOS 3.1设计一种称为"DOS错误映射表"的技术,它将一个更广范围的错误码通过N对3映射到DOS 2.0的3种错误码中。为了获取更精准的新错误码,应用可以额外调用一个新的API(Get Extended Error)。

这项技术仍然存在于Longhorn中,我前几天还去查看了一下源码,在NTVDM相关组件中,不在Win32组件中。不管怎么样,它还活着,而且很可能我们永远无法摆脱它。至少在我们丢弃对16位DOS的支持之前,我们无法摆脱它,这不会很快发生。

从此,微软再也不文档化API返回值的所有错误码,由此将处理潜在出现新错误码的责任从微软转嫁给应用开发人员。

scz: 当年我调用过(Get Extended Error),原来这种设计是为了向后兼容性。。。


文章来源: http://mp.weixin.qq.com/s?__biz=MzUzMjQyMDE3Ng==&mid=2247485189&idx=1&sn=788ad084921a7a62c8e2ed75b90fba9d&chksm=fab2c43acdc54d2c7f9d700085efddb7e66320d0a8cf1308ea8e772ee74d8111a056993bed7f#rd
如有侵权请联系:admin#unsafe.sh