Windows中是否存在某种NULL句柄?如果我通过CreateCompatibleBitmap()
创建一个bmp并通过DeleteObject()
删除它并想要使用移动语义,我想确保不会破坏位图。因此,我必须将HBITMAP
设置为可删除的安全值。与delete nullptr
一样。
答案 0 :(得分:2)
首先是坏消息。由于历史原因,Windows API中通常没有有效的“无效句柄”值。 Windows中的不同子系统将NULL
或INVALID_HANDLE_VALUE
视为无效句柄值(用于返回无效句柄值和获取句柄值)。 Related article on Old New Thing
然而,好消息是因为你仍然需要为意外的返回值做好准备(除非你仔细阅读你使用的每个函数的文档),提供无效值仍然总是“ “在实践中工作。” 您可能没有使用正确的指定“无效”值,但它仍然无效,因此该函数将失败。您的应用程序不会崩溃,除了浪费几个CPU周期之外没有任何负面影响。
因此,请继续使用NULL
(或nullptr
),您对此非常满意。如果不出意外,对于稍后阅读您的代码的人来说,这是直观的。在你的具体例子中,它也是正确的东西,因为GDI函数假定NULL
无效。
您几乎可以信赖NULL
和INVALID_HANDLE_VALUE
都是无效值。虽然我不知道有必要(如文档中明确说明的那样)有效HANDLE
必须为非零,但实际上它们总是如此。我愿意打赌你永远不会找到零值的句柄(只是尝试并使用Sysinternals的handle
工具,你的计算机上的任何一个进程都不会有低于20的句柄。)
但即使假设NULL
可以是一个有效的句柄值,你也必须考虑在调用main
或运行全局构造函数之前已经打开和关闭了一些句柄,你真的不喜欢我有一个选择。这意味着假设NULL
可能是一个有效的句柄,并且假设它在程序运行时仍然有效,那么这个假设句柄在很大程度上与API函数兼容的类型的可能性非常低。
另一方面,有人可能会争辩说应用程序可能会(unsigned) -1
处理打开,呈现INVALID_HANDLE_VALUE
有效值。
除非你泄漏手柄,否则我无法想象你会如何获得那么多打开手柄。但更重要的是,在达到该数字之前很久,您可能会在64位系统上耗尽内存,并且最终会耗尽32位系统的地址空间。
如果INVALID_HANDLE_VALUE
成为一个有效的句柄,那么问题会更严重。
答案 1 :(得分:0)
没有这样的安全价值。将有效HGDIOBJ
之外的任何内容(特别是“逻辑笔,画笔,字体,位图,区域或调色板的句柄”)传递给DeleteObject
会破坏合同并导致程序崩溃。或者它可能会进入调试器,特别是在已检查的操作系统版本上。或者它可以用日志消息填满你的硬盘。或者它可能导致您使AppVerifier失败并阻止徽标认证。或者它可以为您的进程触发“appcompat”规则,并禁用新的Windows功能“以实现向后兼容性”。不要这样做。
您可以使用0
作为占位符,但如果您的句柄为DeleteObject
,则测试该值并且不要调用0
。这与if (p) delete p;
相反,前面的测试被认为是浪费代码。
答案 2 :(得分:-1)
通常0是无效句柄,类似于空指针。
例如,CreateBitmap
如果失败则返回0作为无效的位图句柄。
因此,您可以使用空句柄安全地呼叫DeleteObject
。
来自documentation of DeleteObject
:
如果指定的句柄无效或当前被选入DC,则返回值为零。
此例外是由CreateFile
返回的文件句柄,其中INVALID_HANDLE_VALUE
定义为-1
。