如果你释放一个未清理的设备上下文,会发生什么?

3

通常情况下,如果一个程序将一个对象选择到设备上下文中或者改变它的属性,在释放设备上下文之前它应该将其还原。如果没有这么做会发生什么?

假设我做了以下操作:

HDC hdc = GetDC(some_window);
SelectObject(hdc, some_font);
SetTextColor(hdc, 0x123456);
SetBkColor(hdc, 0xFEDCBA);
SetROP2(hdc, R2_XORPEN);
ReleaseDC(some_window, hdc);

some_window的窗口类没有设置CS_OWNDCCS_CLASSDC标志。会发生什么?


2
http://blogs.msdn.com/b/oldnewthing/archive/2013/03/06/10399678.aspx - Hans Passant
2个回答

3
你列出的功能中,只有 SelectObject 如果对象没有被取消选择(即选择原始对象),会导致问题。这将导致 some_font 资源泄漏,因为 DC 在释放时仍然保持其上打开的句柄。
你应该这样做:
HDC hdc = GetDC(some_window);
HGDIOBJ hOldObj = SelectObject(hdc, some_font);

// ... 

SelectObject(hdc, hOldObj);
ReleaseDC(some_window, hdc);

或者是这个:
HDC hdc = GetDC(some_window);
int nSaved = SaveDC(hdc);
SelectObject(hdc, some_font);

// ... 

RestoreDC(nSaved);
ReleaseDC(some_window, hdc);

根据MSDN注释
每个函数都会返回一个标识新对象的句柄。在应用程序检索到句柄后,必须调用SelectObject函数替换默认对象。但是,应用程序应保存标识默认对象的句柄,并在不需要新对象时使用该句柄替换它。当应用程序完成使用新对象进行绘图后,必须通过调用SelectObject函数恢复默认对象,然后通过调用DeleteObject函数来删除新对象。未能删除对象会导致严重的性能问题。

如果字体永远不会被销毁呢?(直到程序终止) - user253751
如果字体没有使用DeleteObject函数销毁,它实际上会成为资源泄漏。如果您在对象仍被选入设备上下文(DC)时调用DeleteObject函数,则它将(可能)失败。然而,在程序结束时,这可能无关紧要,但这不是一个好的编程习惯。 - Roger Rowland
删除它的合适时机是程序结束时。让操作系统代替显式删除它会有什么不好的影响?但这已经偏离了原问题的主题。 - user253751
1
@immibis 删除显式意味着您知道自己在做什么,而不是依赖默认行为来整理。如果您的代码随后更改,则默认行为可能不再适用,并且将不明显地知道何时和何处不再需要您分配的资源。 - Roger Rowland

0

无法恢复原始字体对象会导致句柄泄漏。操作系统将保留对一些字体(some_font)的句柄。如果重复执行此代码,则每次都会泄漏另一个句柄。您将在任务管理器中看到句柄计数正在增加。如果这种情况持续很长时间,最终会出现呈垃圾状况的绘画失败。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接