诊断RegisterWindowsMessage泄漏

Kev*_*Day 1 winapi resource-leak

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

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

ControlOfs030D000000000270

最后的数字在哪里变化.

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

一些潜在的资源:

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

Rem*_*eau 5

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

还存在由VCL创建的,在形式的另一原子名称"Delphi<ProcessID>",其中<ProcessID>是十六进制格式.

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

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

这最终由Embarcadero于2012年在RADStudio XE3中修复(Andreas Hausladen发布了早期VCL版本的补丁).但是使用较早版本的VCL编译的预先存在的应用程序会受到影响,并且您无法阻止它们泄漏而无需修改它们以使用静态名称RegisterWindowMessage().

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