GCHandle question

I have the following :

int MyInt = 100;

GCHandle gch = GCHandle.Alloc( MyInt, GCHandleType.Pinned );

If i print GCHandle.Target i get 100. Now, if i do :

Myint = 200;

And i print GCHandle.Target i still get 100. Is this normal ?
I thought GCHandle gives me a stable pointer to the object (MyInt).
But it seems as if it copies MyInt somewhere and returns a pointer to the copy.

I am calling a function in an unmanaged DLL that requires a pointer to an int.
This pointer must remain stable for the lifetime of my app since it's value is updated
thru other calls to the DLL. This means that I have to do MyInt = GCHandle.Target to
get the new value every time I call a DLL function that modifies the pointer value.

Is this the only way of getting a stable pointer (no GC and no moving) ?







drinkwaterAsked:
Who is Participating?
 
CeiledConnect With a Mentor Commented:
Yes, the pointers returned from AllocHGlobal() are guaranteed to stay in place. Things that you pin by creating a GCHandle are also guaranteed not to be moved out from under you -- which one you use depends on your needs. If all you want is a buffer where managed APIs can store and retrieve data, go ahead and use AllocHGlobal(). If you want an object that can be passed back and forth between managed and unmanaged code and used intuitively in both contexts, use GCHandle. Make sure to remember to call GCHandle.Free() or FreeHGlobal() when you're done with it, though.
0
 
CeiledCommented:
The reason your integer gets "copied" somewhere else and then written to is because int is a value type. When you cast a value type to "object," the value gets boxed (that is, copied to a new location on the stack). But don't be discouraged -- once pinned, boxed values *can* be modified, you just have to know how to do it. Here's a sample:

      GCHandle h = GCHandle.Alloc(100, GCHandleType.Pinned);
      Console.WriteLine(Marshal.ReadInt32(h.AddrOfPinnedObject()));
      Marshal.WriteInt32(h.AddrOfPinnedObject(), 500);
      Console.WriteLine(Marshal.ReadInt32(h.AddrOfPinnedObject()));

All that needs to be done differently is using the Marshal class to set the value, because C# doesn't actually have any syntax for doing what you're trying to do. Note also that you can just look at h.Target to get the value, but it's going to be slightly less efficient because under the covers, it will go to the location on the heap where the int was boxed before, pull the integer out, then box it again. Using Marshal.ReadByte() will return the int directly on the stack, avoiding the extra boxing operation.

Don't forget to Free() the handle when you're done with it (or those four bytes will never be deallocated), and you should be good. Hope this helps.
0
 
CeiledCommented:
Er...the parentheses on "the value gets boxed" should read "that is, copied to a new location on the HEAP," not the stack. Sorry for the confusion.
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
drinkwaterAuthor Commented:
Aha, so that's what boxing is ! My main concern is that the pointer never move or be garbage collected. The Int example is just one case. But I have other cases where I need a pointer to a buffer (again must not move or be GC). If I use Marshal.AllocHGlobal which returns an IntPtr - can I be sure that it will never move or be GC ? Remember I am passing
the pointer to an unmanaged DLL which stores the pointer and uses that pointer in other calls to the DLL
0
 
AlexFMCommented:
Result of Marshal.AllocHGlobal is pointer to unmanaged memory block which is not subject of garbage collecting and will never be moved.
IntPtr structure itself, however, can be moved by GC, but it's value remains the same and memory block pointed by it will not be moved.
0
 
landerson999Commented:
Hey Ceiled, dont want to highjack a questino, although this one has been answered, and experts-exchange don't have the ideas to put in a request member to view your question button, so I hope you could take a look over at http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_23595254.html as I have a similar problem using the gchandle, which isn't quite working out...
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.