views:

346

answers:

3

Our application is failing on one specific user's computer with ERROR_NOT_ENOUGH_MEMORY ("Not enough storage is available to process this command").

The error is apparently being raised somewhere deep within the Delphi VCL framework that we're using, so I'm not sure which Windows API function is responsible.

Is memory a problem? A call to GlobalMemoryStatus gives the following information:

  • dwTotalPhys - 1063150000 (~1 GB)
  • dwAvailPhys - 26735000 (~27 MB)
  • dwAvailPage - 1489000000 (~1.4 GB)

It seems strange to me that Windows would let the available physical memory get so low when so much space is available in the paging file, but I don't know enough about Windows' virtual memory management to know if this is normal or not. Is it?

If not memory, then which resource limit is being hit? From what I read online, ERROR_NOT_ENOUGH_MEMORY could be the result of the application hitting any of several limits (GDI objects, USER objects, handles, etc.) and not necessarily memory. Is there a comprehensive list of what limits Windows enforces? Is there any way to find out which limit is being hit? I tried Google, but I couldn't find any systematic overview.

+2  A: 

A more common cause this error than any of those you've listed is fragmentation of Virtual Memory Space. This a situation where whilst the total free memory is quite reasonable the free space is fragmented with various bits of the virtual memory space being currently allocated. Hence you can get an out of memory error when a request for memory cannot be satisfied by a single contiguous block despite the being enough in total free.

AnthonyWJones
That should be fairly easily checkable by trying the same thing from a fresh reboot. One would think they would have tried that before posting it as a question on SO (but dumber things have happened...)
T.E.D.
@T.E.D. : A reboot isn't any more effective than simply killing the faulting process and trying again. Each process has its own fresh Virtual memory space when it is first created. The problem usually arises naturally in a long running app or quickly where there is a mixture of large and small chunks of memory being allocated and deallocated fairly rapidily whith different lifetimes. Its usually an indicator that some chunk of code ought be maintaining a list of buffers to re-use rather than constantly allocating and releasing memory.
AnthonyWJones
+2  A: 

Check all the possibilities.

GDI-problems can be monitored using the free GDIView utility. Its a single file that users can start without a installer.

Also, install the ProcessExplorer on the machine concerned.

If you have no access to the machine, ask the user to make screenshots of the status monitored by the applications. Very likeley, this will give you some hint.

RED SOFT ADAIR
A: 

The culprit in this case was CreateCompatibleBitmap. Apparently Windows may enforce fairly strict systemwide limits on the memory available for device-dependent bitmaps (see, e.g, this mailing list discussion), even if your system otherwise has plenty of memory and plenty of GDI resources. (These systemwide limits are apparently because Windows may allocate device-dependent bitmaps in the video card's memory.)

The solution is simply to use device-independent bitmaps (DIBs) instead (although these may not offer quite as good of a performance). This KB article describes how to pick the optimal DIB format for a device.

Other candidates for resource limits (from others' answers and my own research):

Josh Kelley