The Case of the Not Enough Storage Error in a Delphi Application

The Problem

After a few weeks Delphi applications running on Windows Server (2008 or later) will fail to start or create new windows with error 8: Not enough storage is available to process this command.

Possible Cause 1: Desktop Heap Exhaustion

Session 0 which service applications are running in gets allocated substantially less desktop heap than interactive sessions, so you might be running out of it. There is a system event log entry with event ID 243 or 244 when the desktop heap gets exhausted.

By increasing the values in the SharedSection part of the data in registry value “Windows” in key “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems”, you can allocate more to the service session, as described in this Microsoft support article or this Stack Overflow answer.

Note that Microsoft’s Desktop Heap Monitor tool no longer works on current versions of Windows Server.

Possible Cause 2: Atom Leak

Applications compiled with Delphi XE2 or earlier call RegisterWindowMessage in the initialization section of Controls.pas to allocate a unique window message ID. This takes up one slot in the session’s atom table. Unfortunately, there are only around 16 000 slots in the atom table. With no way to unregister a window message, you will eventually run out of them. It has been said that on earlier versions of Windows, the counter wrapped around so you never ran out as slots got overwritten/reused.

For more details, see this bug report on Embarcadero’s Quality Central and this Stack Overflow answer.

I fixed this by editing the Controls.pas unit replacing this line

RM_GetObjectInstance := RegisterWindowMessage(PChar(ControlAtomString));

with this one

RM_GetObjectInstance := RegisterWindowMessage(PChar('DelphiRM_GetObjectInstance'));

This way all Delphi applications share the same atom instead of creating their own. There is also a more involved fix by Andreas Hausladen, but this solution sufficed for me.

Analyzing the Atom Leak

Jordi Corbilla has written the super useful Atom Table Monitor which dumps entries from the atom table. I made a C# version of it, the Atom Table Dumper, because (a) I didn’t want to diagnose issues with my Delphi applications using another Delphi application that had the same issue and (b) I needed an easier to read and process output format.

Note that your analysis tool has to run in the same session as the application getting the error.

Further note that not all of the atoms listed under RegisteredWindowMessage were necessarily allocated by RegisterWindowsMessage. RegisterClass is another function that allocates atoms in this table. However, as the documentation points out “All window classes that an application registers are unregistered when it terminates.“ so having many of them (temporarily) isn’t necessarily a problem.

Museum Insel Hombroich (again)

After my previous visit to Museum Insel Hombroich was cut short by rain, I went again this week when the weather was nicer.

Obviously, it was a much more enjoyable visit. Museum Insel Hombroich just has this wonderful combination of art…




Außenansicht Ecke

Rundes Haus

Fenster Klein

…and nature.




Powerlines I came across while walking back to Neuss. #symmetry

Strommast Totale

Strommast Klein

Museum Insel Hombroich

The museum Insel Hombroich is a large park with several sculpture, installations and architecturally interesting buildings housing artwork. Even though it is not far from Düsseldorf, it’s a bit difficult to reach by public transportation, so until yesterday I had never been there.


Unfortunately, I picked the worst possible time to go. The weather was OK when I got there, but once I had gone past the first building, what started as a drizzle soon turned into a downpour.

Außenansicht Ecke

Decke (1)

Decke Klein

I walked around for a while, but couldn’t really enjoy it as I was getting soaked by the rain.


I eventually went back to the bus stop, and only then did the rain stop and the sun came out. Since there is only one every other hour, I called it a day and decided to come back some other time. Even from what little I’d seen, it’s definitely worth another visit.


Pictures from Milan Part 3

After part 1 City Center and part 2 Modern Architecture, here is part 3 with the remaining pictures from last week’s trip to Milan.

Pirelli HangarBicocca

HangarBicocca is an old factory that a few years back was transformed into an impressive exhibition space. It features a permanent installation by Anselm Kiefer called The Seven Heavenly Palaces.

Hangar Bicocca Entrance

These pictures really don’t do it justice. It’s just so impressive to be standing in a huge darkened hangar amid these 14-18m high houses. Interestingly, the paintings work both from afar, when you can take them in as a whole, as well as from up close, when they reveal a totally different layer of detail.

Hangar Bicocca Bild Klein

Central Station

Despite the massive size of Milan’s Central Station, a lot of attention was paid to getting the details right as well.

Central Station Klein

Central Station (4)

Central Station (2)

Central Station (3)

Central Station (5)

Pictures from Milan Part 2: Modern Architecture

The part of Milan that made the biggest impression on me was no doubt the Porta Nuova district consisting of modern skyscrapers and high-rise residential buildings such as Bosco Verticale (“vertical forest”) and the UniCredit Tower.

We first went there on Saturday evening as the sun was setting and live-music was playing on the Piazza Gae Aulenti. It was a wonderful scene. I came back on sunny Monday morning to capture these beautiful shots.

Bosco Verticale & UniCredit Klein

UniCredit Tower Klein

Piazza Gae Aulenti Skyscraper Klein

Porta Nuova Park

The elegant Grattacielo Pirelli (Pirelli Tower) reflecting the morning sun.

Grattacielo Pirelli

Pictures from Milan Part 1: City Center

First up in a series of pictures from my visit to M in Milan are the classics in the city center, starting with the must-see Milan Cathedral.


The Cathedral, the highest building in central Milan, seen from Piazza San Babila, a few blocks away.

Cathedral from afar

The luxurious Galleria Vittorio Emanuele II shopping mall.

Galleria Vittorio Emanuele II Klein

Galleria Vittorio Emanuele II Innen

For a second, I thought I was in the wrong Italian city when I saw this mosaic.


Torre Branca feels a little out of place among the classic building of Parco Sempione.

Torre Branca

Watch out mixing String and PChar in Delphi

Rudy Velthuis has written an excellent article about PChar in Delphi. Whenever someone comes up to me with a PChar/string question, I refer them to that article.

There are, however, a few caveats one needs to be aware of when mixing string and PChar that he does not mention. This is what I want to cover in this brief article.

The problems mixing string and PChar described here are caused by null characters (or #0 in Delphi syntax). Since Delphi strings have a length counter, It is perfectly legal for them to contain #0. Since PChar are null-terminated, by definition they cannot contain #0.

However, a few Delphi routines that seem to operate on strings internally actually operate on PChar. They will therefore not work as expected when the string they are given contains #0.

You cannot replace #0 in a string

If you call StringReplace to replace #0, it simply won’t work.

function RemoveNull(AInput: string): string;
  Result := StringReplace(AInput, #0, '', [rfReplaceAll]); // Won’t work

It seems that all replacing routines internally cast to PChar making them useless for this. Instead you will have to do a character by character comparison as in this routine by David Heffernan.

StrPCopy stops at #0

The StrPCopy routine takes a string as an input and copies it into a PChar. I used to use this routine in a TStringBuilder-like class which used a PChar to refer to an internal buffer containing the string being built. It also had a length counter, so one would not have to scan the PChar to figure out its length.

But even though StrPCopy takes a string as its input and could thus have access to its length, it does not copy all character, but stops at the first #0.

If you really want to copy all characters, you’ll have to use a routine such as Move that copies bytes not characters as in this example (again by David Heffernan).

Beware of implicit conversions

Since the compiler supports implicitly converting between PChar and string, you will often get away with passing a PChar where a routine takes a string parameter. The compiler will just generate a temporary string from the PChar and pass that instead.

Hence, this code will compile and work just fine:

function GetSubstring(AInput: PChar; AStart, ASubstringLength: Integer): string;
  Result := Copy(AInput, AStart, ASubstringLength); // Works, but is slow

Unfortunately, it has horrible performance, because the compiler needs to know the length of the PChar in order to built that temporary string. And the only way to figure out the length of a PChar is to check every character until the first #0.

See this question I asked on Stack Overflow how to fix this with a PChar-equivalent for the Copy routine.