问题描述
一台站机管理m台分机,测试多分机时,发现如下现象:当分机数位400时,界面卡死;当分机数为200时,一切正常。
由于界面刷新是通过定时器来不停刷新界面的,于是在定时器处理函数中添加断点。但该断点一直没执行。
在msdn上查Cwnd::SetTimer说明,该函数正常返回非零数值,失败则返回零。检查SetTimer返回值,在失败情况下,通过GetLastError()获取最近的错误代码。结果发现SetTimer失败,错误码为1158.
在MSDN是这样藐视1158的:
ERROR_NO_MORE_USER_HANDLES 1158 (0x486)
The current process has used all of its system allowance of handles for Window Manager objects.
分析过程
不清楚“handles for window manager objects”什么意思,字面意思是窗口管理对象句柄。于是通过“任务管理器”来查看该软件对应的句柄数和线程数,结果发现句柄数和线程数分别为555和14,和其他进程对比,并不是特别多。
在网上搜索相关资料,有篇文章说,打开“任务管理器”的"用户对象"列,观察其数值,如果接近10000,就必须优化(操作系统为每个进程最多分配10000个用户对象)。结果发现9484。这个数目确实多。
接下来,顺着程序启动流程来定位问题所在。基本方法是:断点和观测用户对象数。
最后确定了出错地点:在注油器构造函数中,初始化了5倍分机数的非模态弹出消息框。由于分机数为375,所以有1875个弹出框(如果每个弹出框有5个用户对象,则有9375个用户对象)。