Click here to Skip to main content
15,885,775 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
why it return NULL? And How can I fix it?

I had used GetLastError() to catch error code and it return 6 (invalid Handle).
But I dont know why.

Help me to sold it, thanks so much..

Untill now, I havent solution to fix this problem.
Posted
Updated 7-Mar-13 23:50pm
v3

Even if you follow a 'memory allocate' request with a 'free', a reasonable size memory request might not be available after some time. If the allocations are 'large' or are different sizes (or several other reasons), the memory available will get fragmented over time and memory will not be available. Fact of life.

Some of the things you can do to help with the situation:
- Use new and delete (not malloc/calloc/realloc/free)
- Implement a memory pool
- Allocate what you can on the stack
- Make sure you don't have leaks
- If you allocate/free something in a loop, do the 'free' logic in the reverse order from allocations
- If have a heap based buffer, start it with a reasonably 'large' size and expand it if it becomes too small. Hang on to this 'largest' size buffer.
 
Share this answer
 
Comments
Hieu388 7-Mar-13 21:45pm    
Thanks H.Prydon so much.

But it's still have problem..

When it occur applycation error. I used code below to show physical memory.
///////////////////////////////////////////////
MEMORYSTATUS MemStat;

memset(&MemStat, 0, sizeof(MemStat));
MemStat.dwLength=sizeof(MemStat);
GlobalMemoryStatus(&MemStat);

int nAvailPhysMB = MemStat.dwAvailPhys / (1024*1024);
//////////////////////////////////////////////
I see available physical memory is over 200MB. I dont think that application error from memory leak.

I also use GetLastError() to get error code. It return 6 "Invalid handle" but what is handle in here?

This is my direct code:
//
pDIB = (BYTE*)GlobalAllocPtr( GHND, DIBsize ) ;
//
Jochen Arndt 8-Mar-13 5:36am    
GlobalAllocPtr() is a macro: GlobalLock(GlobalAlloc((flags), (cb)))
When there is not enough memory, GlobalAlloc() will fail and return NULL. The return type of GlobalAlloc() is a HGLOBAL: A handle to a global memory object. When passing such a NULL handle to GlobalLock(), it will return NULL and set the last error to 6 (ERROR_INVALID_HANDLE).

So it seems that you are using up all your memory. A possible reason is that you are not freeing your memory. When using GlobalAllocPtr(), the memory must be freed using GlobalFreePtr(). When passing the memory object to the system, it must be unlocked before. Otherwise the system can't free it because there is still a lock count:

pDIB = (BYTE*)GlobalAllocPtr( GHND, DIBsize );
// Copy data to memory here
// Option1: Memory no longer used: Free it using GlobalFreePtr(pDIB)
// Option2: Unlock the memory before passing it to
// somewhere else that takes ownership of the memory:
HGLOBAL hGlobal = GlobalPtrHandle(pDIB);
GlobalUnlock(hGlobal);
// Pass global memory to function that takes ownership of the memory
FuncExpectingAHGLOBAL(hGlobal);
Hieu388 8-Mar-13 6:15am    
Thanks for your help.
In Option 1: I had used and this error still have.
In Option 2: I will try it and report to you later.

I have a question: When size need to allocate larger than 512KB, GlobalAllocPtr() does not using Heap memory any more, in this case GlobalAllocPtr() using direct Virtual Memory to allocate memory. And then when free memory by GlobalFreePtr(), does it work? because I think GlobalFreePtr() work in Heap memory, not in Virtual Memory
Any help from you?
Thank you so much.
Jochen Arndt 8-Mar-13 6:31am    
GlobalAlloc() memory is on the heap. See http://msdn.microsoft.com/en-us/library/windows/desktop/aa366574%28v=vs.85%29.aspx.

In general you should use global memory only when it is required (passed as parameter to some function, e.g. clipboard and drag & drop operations).
In all other cases you should use new / delete.

I would also suggest to not use the macros. Use the pure functions. So you have a better overview of the usage and locking and can check for errors when they occur and not later (if GlobalAlloc() fails it will set an error code which is overwritten by GlobalLock() when using the GlobalAllocPtr() macro):

HGLOBAL hGlobal = ::GlobalAlloc(nSize);
if (NULL == hGlobal)
{
// out of memory; show error message and/or return failure state
return; // out of memory
}
// Lock the memory and get a pointer to it
pDIB = (LPBYTE)::GlobalLock(hGlobal);
// Do something with the memory
::CopyMemory(pDIB, lpSrc, nSize);
// Pass memory to other function to do somethin with it
SomeFunc(pDIB);
// Unlock memory so that it can be accessed by others and freed
::GlobalUnlock(hGlobal);
// Pass global memory to other function
SomeFunc(hGlobal);
// If function does not take ownership of memory, free it
::GlobalFree(hGlobal);
Hieu388 7-Mar-13 21:48pm    
I also make size lager when it small. above 512* 1024 bytes, but it's still happen.
It occur when run >1500 times. Do you give me a hint?
You didn't call GetLastError as recommended by the documentation[^], did you?
 
Share this answer
 
Comments
Hieu388 8-Mar-13 6:21am    
I called GetLastError after GlobalAllocPtr() return NULL.

/////////////////////////////
pUpdateImageDIB = (BYTE*)GlobalAllocPtr( GHND, DIBsize ) ;
if( pUpdateImageDIB == NULL )
{
DWOR dwError = GetLastError() ;
}
/////////////////////
I see it return 6 (Invalid Handle).
I dont know why? Because I had used GlobalFreePtr() to free memory.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900