诊断RegisterWindowsMessage泄漏 [英] Diagnosing RegisterWindowsMessage leak

查看:88
本文介绍了诊断RegisterWindowsMessage泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在其中一个应用程序的生产服务器上看到原子池资源耗尽.

We are seeing atom pool resource exhaustion on production servers of one of our applications.

使用出色的AtomTableMonitor工具,我们通过RegisterWindowsMessage调用将问题隔离为创建大量原子.他们都有这样的名字:

Using the fantastic AtomTableMonitor tool, we've isolated the issue to creation of a huge number of atoms by the RegisterWindowsMessage call. They all have names like this:

ControlOfs030D000000000270

ControlOfs030D000000000270

末尾数字更改的地方.

我的问题是:我们如何确定正在创建这些原子的过程?

My question is: How do we figure out which process is creating these atoms?

一些潜在资源:

https://blogs.msdn.microsoft.com/ntdebugging/2012/01/31/identifying-global-atom-table-leaks/

推荐答案

"ControlOfs..."开头的原子是由Delphi/C ++ Builder中的Borland/Embarcadero的VCL(可视化组件库)框架创建的.这些原子实际上是"ControlOfs<HInstance><ThreadID>"的形式,其中<HInstance><ThreadID>是十六进制格式的(因此,在您的情况下为HInstance = 0x030D0000 = 51183616ThreadID = 0x00000270 = 624).

Atoms that begin with "ControlOfs..." are created by Borland/Embarcadero's VCL (Visual Component Library) framework in Delphi/C++Builder. These atoms are actually in the form of "ControlOfs<HInstance><ThreadID>", where <HInstance> and <ThreadID> are in hex format (so, in your case, HInstance = 0x030D0000 = 51183616, ThreadID = 0x00000270 = 624).

VCL还创建了另一个原子名称,其形式为"Delphi<ProcessID>",其中<ProcessID>为十六进制格式.

There is also another atom name that is created by the VCL, in the form of "Delphi<ProcessID>", where <ProcessID> is in hex format.

这意味着使用VCL的应用程序的每个实例都会创建一个新的唯一"Delphi..."原子,并且其主UI线程也会创建一个新的唯一"ControlOfs..."原子(这些原子用于将TWinControl对象指针存储在VCL通过SetProp()创建的HWND,供VCL的FindControl()IsDelphiHandle()实用程序功能使用).这两个原子在应用程序启动时都已在GlobalAddAtom()中注册,而在应用程序关闭时已在GlobalDeleteAtom()中未注册,因此没有泄漏.

This means that every instance of an app that uses the VCL creates a new unique "Delphi..." atom, and its main UI thread creates a new unique "ControlOfs..." atom (these atoms are used to store TWinControl object pointers in VCL-created HWNDs via SetProp(), for use by the VCL's FindControl() and IsDelphiHandle() utility functions). Both atoms are registered with GlobalAddAtom() at app startup, and unregistered at app shutdown with GlobalDeleteAtom(), so there is no leak.

但是,从DELStudio/C ++ Builder 6一直到RADStudio XE2,还有另一个原子使用相同的"ControlOfs..."名称.该原子是使用RegisterWindowMessage()创建的(用于私人RM_GetObjectInstance窗口消息),不能取消注册.因此,每次运行受影响的VCL应用程序时,都会创建此唯一原子并随后将其泄漏.

However, in Delphi/C++Builder 6 all the way up to RADStudio XE2, there is yet another atom that uses the same "ControlOfs..." name. This atom is created with RegisterWindowMessage() (for a private RM_GetObjectInstance window message), which cannot be unregistered. So, every time an affected VCL app is run, this unique atom is created and subsequently leaked.

该问题最终在2012年由Embarcadero在RADStudio XE3中修复(Andreas Hausladen发布了修补程序以获取较早的VCL版本).但是,使用较早版本的VCL编译的现有应用程序会受到影响,并且您无法做任何事情来阻止它们泄漏而无需修补它们以在RegisterWindowMessage()中使用静态名称.

This was eventually fixed by Embarcadero in RADStudio XE3 in 2012 (Andreas Hausladen posted a patch for earlier VCL versions). But pre-existing apps that are compiled with older versions of the VCL are affected, and there is nothing you can do to stop them from leaking without patching them to use a static name with RegisterWindowMessage().

因此,通过结合使用AtomTableMonitor和任务管理器来回答您的问题,您应该能够确定正在运行的应用程序是VCL应用程序,然后可以单独检查它们是否泄漏原子.或者,将 SysInternals进程监视器Thread Create过滤器结合使用,以获取线程ID及其创建过程的列表,然后您可以将这些线程ID与泄漏的原子名称进行匹配.

So, to answer your question, using a combination of AtomTableMonitor and Task Manager, you should be able to figure out which apps you are running are VCL apps, and then you can check them individually for leaking atoms. Or, use SysInternals Process Monitor with a Thread Create filter to get a list of thread IDs and their creating processes over time, then you can match up those thread IDs to the leaked atom names.

这篇关于诊断RegisterWindowsMessage泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆