我现在支持的产品似乎消耗了大量的桌面堆.二进制文件大多是.net,并且都将会话0作为非交互式进程运行(它们都是已安装的Windows服务的子进程).所以,据我所知,他们不应该消耗任何桌面堆.
我们在系统日志中有几个环境报告事件ID 243,然后间歇性地在应用程序日志中记录事件ID 1000; 应用程序日志中的异常始终为0xc0000142.最终,我们的一项服务也会因一些神秘(无用)的消息而崩溃.不幸的是,我们从来没有能够捕获异常,但这些似乎都是桌面堆耗尽的非常明确的指标.
我正在试图找出消耗这么多桌面堆的东西,以便我可以追踪原因.但这是我陷入困境的地方.最初我计划安装Desktop Heap Monitor,但是在尝试使用它之后,我意识到它在XP之后的任何东西都不受支持.我在某处读过Process Explorer应该能够给我相同的信息,所以我们一直在监视PE中的以下对象:
报告事件243时的"处理计数"值与未发生问题的几天之前或者甚至在启动过程的几分钟内没有显着差异.并且GDI和USER对象都是零.所以,我真的不知道究竟可能耗尽桌面堆,或者就此而言,如何进一步调试它.我在某处看到WeakEventManager可能导致这个问题,但我们似乎并没有使用它.
我在google和SO上都搜索过这个东西,到目前为止我还没有找到任何东西.我真正想要的是确定哪个进程正在耗尽堆,或者至少哪个进程耗费最多.如果有人对如何做到这一点有任何指示,我真的很感激.
这是一个旧线程,但我认为我会回传以防将来有人遇到这种情况。经过一些调试后,我们确定了哪个进程导致了问题。我决定将WinDbg附加到该进程,并在CreateWindowEx和NtDestroyWindow上设置一个bp。果然,确实调用了CreateWindowEx来创建一个隐藏的窗口。从堆栈上的参数中,我能够获得该Window的类(它始终是相同的),这有助于进一步缩小范围。
随着时间的流逝,我开始注意到对NtDestroyWindow的调用数量少于对CreateWindowEx的调用数量。因此,我下调了调用堆栈,以查看创建Windows的内容……有一个类构造函数和析构函数(本机,非托管)。似乎我们没有像调用构造函数那样频繁地调用析构函数,因此随着时间的流逝,我们泄漏了这些类的某些实例,并且对于每个实例,我们还“泄漏”了一个隐藏的窗口,该窗口随着时间的推移而累积并导致桌面堆耗尽问题。从这里开始,我们设法跟踪了该类实例的销毁位置,并能够解决问题。
但是,我对自己的工作不满意,我很好奇为什么Process Explorer对我没有像我预期的那样有用。一直以来,它一直显示零个用户对象,即使我知道该过程正在创建窗口对象。然后,我意识到PE只能为在同一会话中运行的进程显示此数据。因此,为了跟踪服务的windowo对象,我必须在会话0中运行它。在PsExec和下面的帖子的帮助下,我能够在零会话中运行PE并切换到它。
https://superuser.com/questions/426868/interactive-session-0-in-windows-7
从那里,我确实可以看到该进程有1000多个User Object。我还能够运行WinSpy并确认我的发现。当然,在这个阶段,所有的工作都是学术性的,但这也许对将来的某人有用。
| 归档时间: |
|
| 查看次数: |
1206 次 |
| 最近记录: |