Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 移动语义和窗口句柄。删除对象安全句柄?_C++_Windows_Bitmap_Move Semantics - Fatal编程技术网

C++ 移动语义和窗口句柄。删除对象安全句柄?

C++ 移动语义和窗口句柄。删除对象安全句柄?,c++,windows,bitmap,move-semantics,C++,Windows,Bitmap,Move Semantics,Windows中是否存在某种空句柄?如果我通过CreateCompatibleBitmap()创建bmp,并通过DeleteObject()删除它,并希望使用移动语义,我希望确保位图不会被破坏。因此,我必须将HBITMAP设置为可安全删除的值。与删除空指针类似,0通常是无效句柄,类似于空指针 例如,CreateBitmap如果失败,则返回0作为无效的位图句柄 因此,您可以使用空句柄安全地调用DeleteObject 从: 如果指定的句柄无效或当前已选择为DC,则返回值为零 例外情况是由Creat

Windows中是否存在某种空句柄?如果我通过
CreateCompatibleBitmap()
创建bmp,并通过
DeleteObject()
删除它,并希望使用移动语义,我希望确保位图不会被破坏。因此,我必须将
HBITMAP
设置为可安全删除的值。与删除空指针类似,0通常是无效句柄,类似于空指针

例如,
CreateBitmap
如果失败,则返回0作为无效的位图句柄

因此,您可以使用空句柄安全地调用
DeleteObject

从:

如果指定的句柄无效或当前已选择为DC,则返回值为零


例外情况是由
CreateFile
返回的文件句柄,其中
无效的句柄值定义为
-1
没有这样的安全值。将有效的
HGDIOBJ
以外的任何内容传递给
DeleteObject
会破坏契约,并可能导致程序崩溃,特别是“逻辑笔、画笔、字体、位图、区域或调色板的句柄”。或者它可能会闯入调试器,尤其是在操作系统的已检查版本上。或者它可能会用日志消息填满你的硬盘。或者,它可能会导致AppVerifier失败并阻止徽标认证。或者,它可能会触发进程的“appcompat”规则,并“为了向后兼容”而禁用Windows的新功能。不要这样做


您可以使用
0
作为占位符,但是如果句柄为
0
,则测试该值,并且不要调用
DeleteObject
。这与
if(p)delete p相反首先是坏消息。由于历史原因,Windows API中没有通常有效的“无效句柄”值。Windows中的不同子系统考虑“<代码> null <代码> >或<代码>无效IDHOLYLY值<代码>作为无效句柄值(既返回无效句柄值,又取一个无效句柄)。p>
然而,好消息是,尽管您仍然需要为意外的返回值做好准备(除非您仔细阅读您使用的每个函数的文档),但提供无效值在实践中仍然“有效”。
您可能没有使用正确的指定“无效”值,但它仍然无效,因此函数将失败。您的应用程序不会崩溃,除了浪费几个CPU周期之外,没有其他负面后果

因此,请继续使用
NULL
(或
nullptr
),这样做很好。如果没有其他内容,那么对于以后阅读您的代码的人来说,这是很直观的。在您的具体示例中,这也是正确的,因为GDI函数假定
NULL
无效


您几乎可以相信
NULL
INVALID\u HANDLE\u VALUE
都是无效值。虽然我不知道有效的
句柄必须是非零的要求(如文档中明确说明的),但实际上它们总是非零的。我敢打赌,您永远不会找到值为零的句柄(只要尝试使用Sysinternals的
handle
工具,您的计算机上没有一个进程的句柄可能低于20)

但是,即使假定<代码> null <代码>可以是一个有效的句柄值,也必须考虑到一些句柄已经被打开和关闭,甚至在“代码>主< /代码>被调用或全局构造函数被运行之前,您真的没有选择。这意味着假设

NULL
可能是一个有效的句柄,并且假设它在程序运行时仍然有效,那么该假设句柄与API函数兼容的可能性非常低


另一方面,有人可能认为应用程序可能打开了
(unsigned)-1
句柄,从而使
无效的句柄值
成为有效值

除非你正在泄漏句柄,否则我无法想象你怎么会得到那么多打开的句柄。但更重要的是,在达到这个数字之前,您可能会在64位系统上耗尽内存,在32位系统上肯定会耗尽地址空间。

如果
INVALID\u HANDLE\u VALUE
作为一个有效的句柄曾经成为一个问题,那么您就有了一个更严重的问题。

HBITMAP
是一个
void*
,因此
nullptr
是一个完全可分配的值。CreateCompatibleBitmap失败时返回NULL。所以,我认为最好是设定为nullptr@Chubsdad在C++中,包括C++ 03,在<代码> 0 和 NUL>代码>之间没有任何区别,除了后者只能通过头文件定义获得,并且它可以指定一个除<代码> int 以外的大小。但是,使用
nullptr
时,需要将句柄类型定义为指针,而
0
则不需要这样做。实际上,
HGDIOBJ
当前是指针,但不能保证它是指针,因此使用
nullptr
不是一个好主意。我认为这一行文档的目的是描述可能导致函数失败的条件,而不是保证函数在这些条件下总是安全地失败。在上下文中阅读,其目的是“如果返回值为零,则指定的句柄无效”,这并不保证函数不会引发异常或导致其他有害的副作用。在我看来,如果措辞含糊不清或可疑,最好是防御性地进行编程。@Alf:handle实现的细节(是的,我知道它是一个索引)确实控制着未定义行为的实际结果。但是,它们不会影响未定义行为的边界。即使很容易区分
NULL
句柄