Why RegisterClass fails with ERROR_NOT_ENOUGH_MEMORY?

落爺英雄遲暮 提交于 2019-11-30 12:59:47
  1. You may run out of available virtual address space before you run out of RAM (especially with 32-bit processes). This does not seem to be the case here, however.
  2. The error may refer to running out of some other resource than actual RAM, for example the atoms. Since ATOM is a 16-bit type, there are only 65536 possible atom values. However, global atoms like the window class ones have an even more limited range - 0xC000 through 0xFFFF, giving you only 0x4000 (16384) max registered classes in theory (likely less in practice).

Check the atom values you get from RegisterClass(). If they're getting close to FFFF before erroring out, that's probably your issue.

EDIT: it seems other people has run into the same issue and have identified the culprit:

There is a serious bug in the VCL that will eat up atoms in the private atom table. Windows has a limited number of private atoms in the private atom table (32767), and this is shared by Windows classes, Windows Messages, Clipboard formats, etc. Every time the controls module is initialized, it creates a new Windows Message:

 ControlAtomString := Format('ControlOfs%.8X%.8X', 
                              [HInstance, GetCurrentThreadID]); 
 ControlAtom := GlobalAddAtom(PChar(ControlAtomString));
 RM_GetObjectInstance := RegisterWindowMessage(PChar(ControlAtomString));

The problem is multiplied by the number of DLL's that the application contains that includes the controls module. If you have 10 dll's, and one application, this code will consume 11 atoms every time it is ran.

When the system is ran out of atoms in the private atom table, no window class can be registered. This means, no windowed programs will be able to open after the private atom table is full.

You can also dump the atom table using WinDbg and check for this pattern yourself.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!