windows用户对象或者GDI对象个数限制整理

写这篇文章源自查看一个dump,CEF在创建位图数据的时候崩溃了。

我很纳闷为什么会失败,我首先想到的是程序是不是有资源泄露,导致GDI句柄数过高导致。

把堆栈打印出来发现GDI资源个数0x564个,User对象个数0x5e5个,都才一千多个,应该不多吧。截图如下:

 

所以又查询了下window对GDI和USER对象的个数限制。

msdn介绍GDI对象: https://docs.microsoft.com/zh-cn/windows/win32/sysinfo/gdi-objects

对个数的限制:

There is a theoretical limit of 65,536 GDI handles per session. However, the maximum number of GDI handles that can be opened per session is usually lower, since it is affected by available memory.

Windows 2000: There is a limit of 16,384 GDI handles per session.

There is also a default per-process limit of GDI handles. To change this limit, set the following registry value:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\GDIProcessHandleQuota

This value can be set to a number between 256 and 65,536.

Windows 2000: This value can be set to a number between 256 and 16,384.

系统对每个session的限制是65536(64KB),对每个进程的限制可以通过注册表来修改,范围是256-65536

windows 2000的比较小,做了特殊说明。

特别主要的是专门提到了,会受可用内存的影响。

However, the maximum number of GDI handles that can be opened per session is usually lower, since it is affected by available memory.

 

msdn介绍USER对象: https://docs.microsoft.com/zh-cn/windows/win32/sysinfo/user-objects

对个数的限制:

There is a theoretical limit of 65,536 user handles per session. However, the maximum number of user handles that can be opened per session is usually lower, since it is affected by available memory. There is also a default per-process limit of user handles. To change this limit, set the following registry value:

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

This value can be set to a number between 200 and 18,000.

系统对每个session的限制是65536(64KB),对每个进程的限制可以通过注册表来修改,范围是200 -18000

同样也说明了会受到可用内存的影响!

 

那么dump中查看到当时进程使用的GDI和USER对象个数都是1000多,会不会超过了限制了,需要看下这两个注册表值:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\GDIProcessHandleQuota

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

在我win7和win10电脑上默认值都是10000,所以是远远没有超过限制的。

 

最后,那就很可能是内存不足的原因了吧,然后看了下内存使用情况,果然占用比非常高,可用物理内存也比较小。最终导致创建GDI资源失败了。

 

相关API:

GetGuiResources 获取GDI或者USER对象的个数

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getguiresources


    DWORD dwCount = 0;

    dwCount = ::GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS); // 获取当前进程GDI对象个数

    dwCount = ::GetGuiResources(GR_GLOBAL, GR_GDIOBJECTS); // 获取所有进程对象个数


    dwCount = ::GetGuiResources(GetCurrentProcess(), GR_USEROBJECTS); // 获取当前进程USER对象个数

    dwCount = ::GetGuiResources(GR_GLOBAL, GR_USEROBJECTS); // 获取所有进程USER对象个数

函数第二个参数可以使用另外两个参数:GR_GDIOBJECTS_PEAK,GR_USEROBJECTS_PEAK
不过是需要windows 7 或者 Windows Server 2008 R2以及以上版本才行。

Return the peak count of GDI objects.

Windows Server 2008, Windows Vista, Windows Server 2003 and Windows XP:  This value is not supported until Windows 7 and Windows Server 2008 R2.

 

参考资料:

https://www.xuebuyuan.com/1029053.html

 

 

无关的话题:

msdn中GDI对象以及USER对象放在同一个目录讲解的还包括内核对象:

https://docs.microsoft.com/zh-cn/windows/win32/sysinfo/kernel-objects

文章中的几个图对于理解内核对象的生命周期以及跨进程使用很有帮助。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值