none
Are GCHandles guaranteed to use only the lower 32 bits? RRS feed

  • Question

  • I'm porting an application that has both managed C# code and unmanaged C/C++ code to x64. The code makes liberal use of GCHandles but it passes the handles to the unmanaged code in 32-bit ints instead of using IntPtr/INT_PTR. There is a lot of code to fix, but I'm wondering if I really need to fix it.

    Handles (HWND, HBITMAP, etc.) are guaranteed to only use the lower 32 bits of the 64-bit value. You can safely truncate an HWND by casting it to an int and the handle will still be good. Does this guarantee apply to GCHandle?

    I set HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management\AllocationPreference to 0x100000 to do testing and I saw that memory allocations started using the address space above 4GB (as expected) but the GCHandles I'm getting are still small values like 0x000000000023bcb0. That got me wondering whether GCHandles will never use the upper 32 bits but I need to confirm that before deciding to leave this code alone.

    Wednesday, February 13, 2013 8:51 PM

Answers

  • I do not believe that is the case with GCHandle.  If you want this to work correctly and reliably, you should convert the int values to IntPtr to properly access the memory locations.

    The only reason handles are limited to 32bits is that they are commonly marshaled between 32bit and 64bit processes, so they need consistency.  Pointers, in general, aren't this way, and can use all 64bits.


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Wednesday, February 13, 2013 9:54 PM
    Moderator
  • Check the Reference Source.  Nothing but IntPtrs in the GCHandle structure.
    Wednesday, February 13, 2013 10:16 PM

All replies

  • I do not believe that is the case with GCHandle.  If you want this to work correctly and reliably, you should convert the int values to IntPtr to properly access the memory locations.

    The only reason handles are limited to 32bits is that they are commonly marshaled between 32bit and 64bit processes, so they need consistency.  Pointers, in general, aren't this way, and can use all 64bits.


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Wednesday, February 13, 2013 9:54 PM
    Moderator
  • Check the Reference Source.  Nothing but IntPtrs in the GCHandle structure.
    Wednesday, February 13, 2013 10:16 PM
  • Check the Reference Source.  Nothing but IntPtrs in the GCHandle structure.

    I understand that, but HWND and other handle types are defined as HANDLE. HANDLE is defined as:

    typedef PVOID HANDLE;

    There is nothing there that says that a HANDLE type can be safely truncated to a 32-bit int, yet it can be. What I'm trying to confirm is whether the same is true of GCHandles. There is a ton of coding and testing involved if I need to fix all of this code so if I could get confirmation that GCHandles never use the high 32-bits of the IntPtr I could avoid that work.

    Thursday, February 14, 2013 3:31 PM
  • The only reason handles are limited to 32bits is that they are commonly marshaled between 32bit and 64bit processes, so they need consistency.  Pointers, in general, aren't this way, and can use all 64bits.

    But GCHandles aren't pointers, are they? My understanding is that they are opaque handles. You can only get the pointer to the object if you allocate a pinned GCHandle. This code isn't doing that. It just allocates opaque handles. Maybe those opaque handles follow the same rules as other opaque handles like HANDLE and HWND.
    Thursday, February 14, 2013 3:35 PM
  • The only reason handles are limited to 32bits is that they are commonly marshaled between 32bit and 64bit processes, so they need consistency.  Pointers, in general, aren't this way, and can use all 64bits.

    But GCHandles aren't pointers, are they? My understanding is that they are opaque handles. You can only get the pointer to the object if you allocate a pinned GCHandle. This code isn't doing that. It just allocates opaque handles. Maybe those opaque handles follow the same rules as other opaque handles like HANDLE and HWND.

    GCHandles are effectively "handles" to managed objects.  The managed allocator does not expect managed objects to pass across process boundaries by address, so it does not restrict itself to 32bits like a HANDLE in Win32.

    Assuming 32bits for GCHandle  is NOT safe on 64bit operating systems.


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Thursday, February 14, 2013 3:59 PM
    Moderator
  • "But GCHandles aren't pointers, are they? My understanding is that they are opaque handles. You can only get the pointer to the object if you allocate a pinned GCHandle. This code isn't doing that. It just allocates opaque handles. Maybe those opaque handles follow the same rules as other opaque handles like HANDLE and HWND."

    The IntPtr data type is 32 bit on 32 bit operating systems and 64 bit on 64 bit operating systems. 

    Thursday, February 14, 2013 4:34 PM