Windows 中是否有某种 NULL 句柄?如果我通过创建 bmpCreateCompatibleBitmap()
并通过删除它DeleteObject()
并想要使用移动语义,我想确保位图没有被破坏。因此,我必须将 设置为HBITMAP
可以安全删除的值。喜欢delete nullptr
。
3 回答
先说坏消息。由于历史原因,Windows API 中没有普遍有效的“无效句柄”值。Windows 中的不同子系统将NULL
或INVALID_HANDLE_VALUE
视为无效句柄值(用于返回无效句柄值和获取一个)。关于旧新事物的相关文章。
然而,好消息是,尽管您仍然需要为意外的返回值做好准备(除非您仔细阅读所使用的每个函数的文档),但提供任一无效值在实践中仍然始终“有效”。
您可能没有使用正确的指定“无效”值,但它仍然无效,因此该函数将失败。您的应用程序不会崩溃,除了浪费几个 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
成为一个有效的句柄曾经成为一个问题,那么你有一个更严重的问题。
没有这样的安全值。传递除了有效的任何东西HGDIOBJ
,特别是“逻辑笔、画笔、字体、位图、区域或调色板的句柄”,以DeleteObject
破坏合同并可能使您的程序崩溃。或者它可能会闯入调试器,尤其是在操作系统的检查版本上。或者它可以用日志消息填充您的硬盘。否则可能会导致您无法通过 AppVerifier 并阻止徽标认证。或者它可能会为您的进程触发“appcompat”规则并禁用新的 Windows 功能“以实现向后兼容性”。不要这样做。
您可以用作占位符,但要测试该值,如果您的句柄是.0
则不要调用。这与前面的测试被认为是对代码的浪费相反。DeleteObject
0
if (p) delete p;
通常 0 是无效句柄,类似于空指针。
例如CreateBitmap
,如果失败,则返回 0 作为无效的位图句柄。
因此,您可以使用空句柄安全地调用DeleteObject
。
从以下文档DeleteObject
:
如果指定的句柄无效或当前被选入 DC,则返回值为零。
一个例外是文件句柄,由 返回CreateFile
,其中INVALID_HANDLE_VALUE
定义为-1
。