移动语义和窗口句柄。 DeleteObject安全句柄?

时间:2012-12-12 01:11:05

标签: c++ windows bitmap move-semantics

Windows中是否存在某种NULL句柄?如果我通过CreateCompatibleBitmap()创建一个bmp并通过DeleteObject()删除它并想要使用移动语义,我想确保不会破坏位图。因此,我必须将HBITMAP设置为可删除的安全值。与delete nullptr一样。

3 个答案:

答案 0 :(得分:2)

首先是坏消息。由于历史原因,Windows API中通常没有有效的“无效句柄”值。 Windows中的不同子系统将NULLINVALID_HANDLE_VALUE视为无效句柄值(用于返回无效句柄值和获取句柄值)。 Related article on Old New Thing

然而,好消息是因为你仍然需要为意外的返回值做好准备(除非你仔细阅读你使用的每个函数的文档),提供无效值仍然总是“ “在实践中工作。” 您可能没有使用正确的指定“无效”值,但它仍然无效,因此该函数将失败。您的应用程序不会崩溃,除了浪费几个CPU周期之外没有任何负面影响。

因此,请继续使用NULL(或nullptr),您对此非常满意。如果不出意外,对于稍后阅读您的代码的人来说,这是直观的。在你的具体例子中,它也是正确的东西,因为GDI函数假定NULL无效。

您几乎可以信赖NULLINVALID_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