【发布时间】:2010-10-26 11:48:27
【问题描述】:
我正在尝试在我们的 MFC 代码中查找一个看起来像资源限制问题的问题。内存和CPU看起来不错。根据任务管理器上的进程选项卡,我们的 GDI 对象看起来与其他应用程序一致,但我们的 USER 对象似乎比其他应用程序大 10 倍。
什么是“USER 对象”,有什么限制?
【问题讨论】:
我正在尝试在我们的 MFC 代码中查找一个看起来像资源限制问题的问题。内存和CPU看起来不错。根据任务管理器上的进程选项卡,我们的 GDI 对象看起来与其他应用程序一致,但我们的 USER 对象似乎比其他应用程序大 10 倍。
什么是“USER 对象”,有什么限制?
【问题讨论】:
Mark Russinovich 是这方面的专家。他着有《Windows Internals》一书。幸运的是,不仅有书,还有article dating 2019-06-27。
首先他描述了 USER 对象:
USER 对象之所以得名,是因为它们代表用户界面元素,如桌面、窗口、菜单、光标、图标和加速器表(菜单键盘快捷键)。
然后继续描述极限:
窗口管理器施加的一个基本限制是任何进程都不能创建超过 10,000 个 USER 对象。
和
对 USER 对象数量的一个基本限制来自这样一个事实,即它们的标识符在 Windows 的第一个版本中是 16 位值,即 16 位。在更高版本中添加 32 位支持时,用户标识符必须保持限制为 16 位值,以便 16 位进程可以与窗口和其他由 32 位进程创建的 USER 对象进行交互。因此,65,535 (2^16) 是可以在会话中创建的 USER 对象总数的限制
他还解释了号码mentioned by @Tobi:
由于历史原因,窗口必须有偶数标识符,因此每个会话最多可以有 32,768 个窗口
【讨论】:
阅读所有相关信息here:
对象类别
系统提供三类对象:用户、图形设备接口(GDI)和内核。系统使用用户对象来支持窗口管理,使用 GDI 对象来支持图形,使用内核对象来支持内存管理、进程执行和进程间通信 (IPC)。有关创建和使用特定对象的信息,请参阅相关概述。
和here:
用户对象
用户界面对象仅支持每个对象一个句柄。进程不能继承或复制用户对象的句柄。一个会话中的进程不能引用另一个会话中的用户句柄。
每个会话的理论限制为 65,536 个用户句柄。但是,每个会话可以打开的最大用户句柄数通常较低,因为它受可用内存的影响。用户句柄还有一个默认的每个进程限制。要更改此限制,请设置以下注册表值:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\USERProcessHandleQuota此值可以设置为 200 到 18,000 之间的数字。
【讨论】:
这是一篇“经典”的 MSDN 文章:Give Me a Handle, and I'll Show You an Object
上次我跟踪 Windows 对象泄漏(我怀疑你有)Process Explorer 很方便(handley?)。下窗格可以显示一些已分配的系统对象,此外它还可以进行简单的 USER、GDI 等对象计数。
desktop heap,它是一个内存池,句柄代表生命的真正“东西”(至少是一些句柄,至少不是内核句柄)。有时与其说分配了多少句柄,不如说是该句柄下的每个 object 使用了多少内存。您可以调试堆this way。要安装的是pain。
【讨论】:
我不知道它们是什么,但我知道它们包括窗口句柄。
对于窗口句柄,系统范围的最大值约为 32000,每个进程的最大值为 10000。(这可能只是 USER 对象限制,而不仅仅是窗口句柄。)
如果您以某种方式泄漏窗口句柄,或者如果您使用大量窗口,则窗口句柄的数量可能非常多。 (请注意,即使是像文本标签这样的简单控件也会使用单个窗口句柄。)
【讨论】: