为什么句柄返回值不一致
如果查看返回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?》
- 下一篇: 线程安全:局部静态变量的初始化
- 上一篇: 关闭模态对话框的正确顺序
相关推荐
- ShellExecuteEx的一种玩法
- Posted on 01月04日
- 为什么不能在一个禁用的窗口上显示工具提示?
- Posted on 02月19日
- Visual Studio Code新增ARM支持
- Posted on 12月10日
- 随心所欲地对vcpkg依赖进行版本控制
- Posted on 02月24日
评论已关闭。