none
Tracking handles assigned by GlobalAlloc?

    Question

  • Hi,

    I have run in to a problem where I appear to be leaking handles. These handles do not show up as regular handles so their count is not displayed in Process Explorer or Process hacker etc.

    GlobalAlloc will return a handle if you request moveable memory. Then you can use GlobalLock to convert that handle to a pointer. This is what the GlobalAllocPtr macro does. If you call GlobalAlloc in an infinite loop with the flag GHND you will see it fails after 65536/64k allocations. This is how I know that the handle count is not showing up. I only see 20 handles for process, not 65536.

    GlobalAlloc fails with the error:

    0x00000008 Not enough storage is available to process this command.

    If I change the GlobalAlloc flag to GMEM_ZEROINIT the process will continue until all available memory is exhausted i.e. not hit the 64k handle limit. This is due to the fact that GlobalAlloc returns a pointer, not a handle, for non-moveable memory.

    Does anyone have any references or code on how to track this handle count?

    Example code:

    #include "stdafx.h"
    #include <windows.h>
    #include <windowsx.h>

    int _tmain(int argc, _TCHAR* argv[])
    {
        int count = 0;

        HANDLE currentProc = GetCurrentProcess();

        DWORD handleCount = 0;

        while ( true )
        {

            GetProcessHandleCount( currentProc, &handleCount );

            //LPVOID p = GlobalAllocPtr( GHND, 1068 );
            // LPVOID p = GlobalAllocPtr( GMEM_ZEROINIT, 1068 );

            // GlobalFreePtr( p );

            HGLOBAL gah = GlobalAlloc( GHND, 1028 );

            if ( gah == NULL )
            {
                exit( EXIT_FAILURE );
            }

            LPVOID p = GlobalLock( gah );

            if ( p == NULL )
            {
                exit( EXIT_FAILURE );
            }

    //        HGLOBAL h = GlobalFree( gah );
    //        GlobalUnlock( h );

            ++count;
        }

        return 0;
    }
    Wednesday, July 7, 2010 2:17 PM

All replies

  • check process private bytes
    u have mem leak, not handle leak

    there is no 64k handle limit
    Wednesday, July 7, 2010 3:15 PM
  • Here is the ouput from process explorer for the test code I posted above at the point where the allocation fails. Private bytes is 68,636 K.

    GlobalAllocTest.exe    GlobalAllocTest.exe    5860        68,636 K    138,660 K    69,348 K    69,348 K    69,348 K    69,348 K            0    0    22

    This is only ~60MB. Why can't I make any more allocations using GlobalAlloc? Have I not run out of handles?
    Wednesday, July 7, 2010 5:00 PM
  • maybe "If the heap does not contain sufficient free space to satisfy the request, GlobalAlloc returns NULL"

    globalalloc allocates from default process heap maybe or other heap created with dwMaximumSize set to 2^16

    when u alloc like that max heap size is hit and globalaloc returns null
    Wednesday, July 7, 2010 5:42 PM
  • Well if I change the allocation size to 1 byte GlobalAlloc still fails after exactly 65536 allocations. Only 2968Kb is used this time and Process Explorer only reports 18 handles.

    GlobalAllocTest.exe    GlobalAllocTest.exe    2916        2,968 K    11,684 K    3,676 K    3,676 K    3,676 K    3,676 K            0    0    18

    If I change the allocation flag so that GlobalAlloc does not return a handle but a pointer instead then the test program will run well beyond 65536 allocations ( I stopped the test run at 36234368 allocations before my machine fell over).

    Why, when GloballAlloc returns a handle, does it fail after 2^16 allocations?
    What resource pool are these handles coming from?
    Thursday, July 8, 2010 7:35 AM
  • u r confusing handles with what globalalloc returns

    u r prob hitting implementation detail of globalalloc. unasemble function to check how it works

    check vmmap for more details
    Thursday, July 8, 2010 2:52 PM
  • This post is old, but I was facing the same issue and stumbled on this question, which led me to the solution. The current replies are dead wrong... there is in fact a 64K limit to how many handles can be allocated by GlobalAlloc for moveable memory (GMEM_MOVEABLE.)  For fixed memory, you are limited only by available memory. But for moveable memory, GlobalAlloc returns a handle to the memory and there is a hard limit of 64 K handles. 

    See 

    https://msdn.microsoft.com/en-us/library/ms810603.aspx (search for MOVEABLE)

    also 

    http://winapi.freetechsecrets.com/win32/WIN32GlobalAlloc.htm

    http://www.openroad.org/school/gui/winmem.html


    Wednesday, December 5, 2018 2:08 PM