1
votes

We have a DLL (built using VC2005) that does some processing on behalf of the calling application. This processing requires quite a bit of memory. The DLL creates this memory via heapAlloc like so:

//Allocate space
myStruct* pStackSpace = (myStruct*)::HeapAlloc(m_hStackHeap, 0, sizeof(myStruct));

...
do some processing here
...

//Free space
::HeapFree(m_hStackHeap, 0, pStackSpace);

The heap is allocated via:

m_hStackHeap = ::HeapCreate(0, sizeof(myStruct)*10, 0);

After the create we actually allocate 20 myStructs and then free them just to make sure it handle that. So we know there is enough space.

The issues is that in some case HeapAlloc returns NULL. If that happens we do a HeapValidate(m_hStackHeap, 0, NULL) which always comes back nonezero (meaning all is well). So we know the heap is ok.

We also grantee that we never have more then 10 concurrent allocation at the same time so there should be enough space since the initial heapCreate reserved that much.

The next call to HeapAlloc often succeeds. The behavior is very sporadic. It will work fine, then fail to allocate a few times and then start working fine again.

Any ideas on what is going on?

3
My assumption would be that there must be a problem in tracking concurrent allocations. How are you tracking to ensure you only have 10? - Chad
Have you passed HEAP_GENERATE_EXCEPTIONS as an option? It will tell you which of the two failure modes (out of memory vs. corrupted heap) it hit. - Ernest Friedman-Hill
since you are using DLLs, are you accessing heap, created by one process from another? The memory of a private heap object is accessible only to the process that created it. -- from MSDN - Gene Bushuyev
How do you create the heap? If you're using a limited size heap (e.g. non-zero dwMaximumSize on creation), each allocation is limited to something like 512K, even if the heap is very large. What size does sizeof(myStruct)*10 give you? - André Caron
Andre it is not limited: ::HeapCreate(0, sizeof(myStruct)*10, 0) we are passing zero for the max. - Sam

3 Answers

1
votes

The behavior suggests it could be due to heap fragmentation. You may have sufficient total heap space to satisfy the request but no free blocks large enough. Try using a Low Fragmentation Heap. You can do that by calling HeapSetInformation() to enable LFH. Note that you can't use LFH if you specified the HEAP_NO_SERIALIZE flag in HeapCreate().

0
votes

Rather than use a custom heap you can use custom ALLOC and FREE routines that keep a pool of the appropriate size.

This is done with unioning the struct with a simple object containing a NEXT pointer and one global variable containing a pointer.

If you're out allocate a new one from the global heap.

Where you would have destroyed the heap free all these.

0
votes

2mb structs? Consider using VirtualAlloc and a alloc/free pointer list.