为什么句柄返回值不一致

为什么句柄返回值不一致

作者:BlogUpdater |  时间:2020-12-23 |  浏览:1185 |  评论已关闭 条评论

如果查看返回HANDLE的各种函数, 你就会发现其中一些返回NULL(例如CreateThread),而另一些会返回INVALID_HANDLE_VALUE(例如CreateFile)。所以,你必须查看相关的MSDN文档,才能确定函数在执行失败时的返回值的意义。

为什么句柄返回值如此不一致?

可能你早就猜到了:因为历史原因。

这些句柄的值被这样选择,主要是为了和16位Windows保持兼容。
16位函数OpenFile,_lopen和_lcreat在失败时返回-1,因此32位CreateFile函数返回INVALID_HANDLE_VALUE以便于从Win16移植代码。

(知道了这个,我们就应该可以回答这个问题您现在可以回答以下琐事问题:为什么我想打开一个文件时需要调用CreateFile? 不是应该调用OpenFile吗?答:当然可以,OpenFile是一个更好的名称,但是该名称已被使用。)

另一方面,对于CreateThread或CreateMutex,没有Win16对应的版本,因此它们返回NULL。

由于现在已经为不一致的返回值设置了先例,因此无论何时添加新函数,新函数是否返回NULL或INVALID_HANDLE_VALUE都有些麻烦。

这种不一致有多种后果
首先,当然,你必须小心检查正确的返回值。
其次,这意味着,如果编写通用的句柄包装类,则必须注意两个可能的”非句柄”值。
第三,如果要预初始化句柄变量,则必须以与要使用的功能兼容的方式对其进行初始化。例如,以下代码是错误的:

以上代码有两个错误。
首先,从CreateFile返回的值检查不正确。 上面的代码检查NULL而不是INVALID_HANDLE_VALUE。 其次,代码错误地初始化了h变量。下面是更正后的版本:

第四,你必须特别小心INVALID_HANDLE_VALUE值:巧合的是,值INVALID_HANDLE_VALUE恰好在数值上等于GetCurrentProcess()返回的伪句柄。许多内核函数都接受伪句柄,因此,如果你搞砸了并且不小心在一个失败的INVALID_HANDLE_VALUE句柄上调用了WaitForSingleObject,实际上你将最终等待自己的进程。
当然,这种等待永远不会完成,因为当退出某个进程时会发出信号,因此你最终要等待你自己。

总结
如有必要,请检查每一个Win32 API的返回值。

最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《Why are HANDLE return values so inconsistent?》

标签:

评论已关闭。