Windows的“用户对象”是什么?

15

我正在追踪我们的MFC代码中出现的问题,看起来像是资源限制问题。内存和CPU看起来都很好。根据任务管理器上的进程选项卡,我们的GDI对象看起来符合其他应用程序的要求,但是我们的USER对象似乎比其他应用程序高出10倍。

"USER对象"是什么,以及它们有哪些限制?

4个回答

14

这是一篇“经典”的 MSDN 文章:给我一个句柄,我将给你展示一个对象

上次我在跟踪 Windows 对象泄露(我猜想你也有这个问题),Process Explorer非常方便。它的下面板可以显示一些已分配的系统对象,并且可以对简单的 USER、GDI 等对象进行计数。

桌面堆栈是一个内存池,实际上是句柄所代表的“东西”所在(至少是一些句柄,至少不包括内核句柄)。有时候不仅仅是要关注您已经分配了多少句柄,而更应该考虑每个句柄下面的 对象 使用了多少内存。您可以通过这种方式来调试堆栈。它是痛苦的过程,需要安装。


12

点击这里可以了解更多详情:

对象类别

系统提供三种对象类别:用户、图形设备接口(GDI)和内核。系统使用用户对象来支持窗口管理,使用 GDI 对象来支持图形,而使用内核对象来支持内存管理、进程执行和进程间通信(IPC)。如需有关创建和使用特定对象的信息,请参阅相关概述。

点击这里可以了解更多详情:

用户对象

用户界面对象每个对象仅支持一个句柄。进程无法继承或复制用户对象的句柄。在一个会话中的进程无法引用另一个会话中的用户句柄。

每个会话理论上最多可以有 65,536 个用户句柄。但实际上,每个会话打开的用户句柄数通常较低,因为它受可用内存的影响。每个进程还有一个默认的用户句柄限制。若要更改此限制,请设置以下注册表键值:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\USERProcessHandleQuota

该值可以设置为200到18,000之间的数字。


当我将注册表设置更改为17999并重新启动进程后,它仍然崩溃。这是否需要重新启动或其他操作才能应用? - Florian Straub
@FlorianStraub:很可能需要重新启动,因为这些对象可以从用户模式访问,但内核仍然处理对它们的访问。因此,内核需要刷新,这只能通过重新启动来完成。 - Thomas Weller

4

马克·鲁辛诺维奇是该主题的专家。他写了书籍《Windows Internals》。幸运的是,不仅有这本书,还有一篇2019年6月27日发布的文章

首先,他描述了用户对象:

USER对象得名于它们代表用户界面元素,例如桌面、窗口、菜单、光标、图标和加速表(菜单键盘快捷方式)。

然后继续描述限制:

窗口管理器施加的一个基本限制是,任何进程都不能创建超过10,000个USER对象。

以及

关于USER对象数量的一个根本限制源于其标识符在最初的16位Windows版本中是16位值。当32位支持在以后的版本中添加时,USER标识符必须保持限制为16位值,以便16位进程可以与由32位进程创建的窗口和其他USER对象进行交互。因此,在会话上可以创建的USER对象总数的限制为65,535(2^16)。

他还解释了由@Tobi提到的数字

出于历史原因,窗口必须具有偶数标识符,因此每个会话最多可以有32,768个窗口。


1

我不知道它们是什么,但我知道它们包括窗口句柄。

对于窗口句柄,系统范围内最大约为32000,每个进程的最大值为10000。(这可能只是用户对象限制,而不仅仅是窗口句柄。)

如果你在某种方式下泄漏窗口句柄,或者使用大量的窗口,那么窗口句柄的数量可能非常高。(请注意,即使像文本标签这样的简单控件也会消耗一个窗口句柄。)


2
有关 Microsoft 是否提到了 32000 限制? - Thomas Weller
1
我遇到了进程的10000限制。一旦达到限制,当尝试创建新的winforms对象时,您将收到“错误创建窗口句柄”的消息。 - Bill Tarbell
@ThomasWeller:Aardvark发布的链接提到64K作为全局限制,但那是针对Windows NT的。 - Florian Straub
1
@FlorianStraub:请参考我的答案https://dev59.com/qnNA5IYBdhLWcg3wrf43#62044509,其中解释了这两个数字。 - Thomas Weller

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