-
Grr, garbage collector, stay away from my arrays!
Hi;
I need a memory block allocated on heap (on a fixed posisiton) that GC can't move. I need this because unmanaged code will read data from this memory block on a multi-threaded manner (so "fixed" statement will not work since threads in unmanaged code may still be manipulating this memory though code flow fell out of fixed scope).
Is this possible with C#? Or do you recommend using nasty GlobalAlloc api to allocate memory on heap manually from C#?
Thanks all...
-
Re: Grr, garbage collector, don't move my arrays!
Look it up pin_ptr, MSDN has info.
-
Re: Grr, garbage collector, don't move my arrays!
Thanks for reply but AFAIK, pin_ptr is specific for managed C++ (or am i wrong?). I need a solution for C#. Thanks anyway...
-
Re: Grr, garbage collector, stay away from my arrays!
Code:
GCHandle objHandle = GCHandle.Alloc(array);
// do whatever
objHandle.Free();
if you have an array of value types you can also pin the array:
Code:
GCHandle objHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
if they're reference types you cant pin it, but that will keep GC from messing w/ it.
-
Re: Grr, garbage collector, don't move my arrays!
What about:
Code:
IntPtr addressOfMyBuffer = Marshal.AllocHGlobal(yourArrayHere);
-
Re: Grr, garbage collector, don't move my arrays!
Oh if only people would read the documentation....
fixed statement
-
Re: Grr, garbage collector, don't move my arrays!
.NET does has a way of handling this. Use InteropServices and create a GCHandle for your buffer (array).
Code:
using System.Runtime.InteropServices;
...
GCHandle pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
The Pinned GCHandleType tells the garbage collector to pin the array into place so, even when compacting memory, it won't move it. To obtain an IntPtr for that address use
Code:
IntPtr ptrToPinned = pinnedBuffer.AddrOfPinnedObject();
Now you can pass the ptrToPinned to any unmanaged method. When you are done with it, you can let the garbage collecter now by calling
Code:
pinnedBuffer.Free();
I suggest you place the code in a try - finally block to make sure the memory is freed even if an exception occurs.
-
Re: Grr, garbage collector, don't move my arrays!
you cannot pin or obtain the pointer to or get the size of reference types.
GCHandle is what you need. you can pin it if its members are value types, otherwise you cant, but allocating the handle will keep you from having it moved around.
-
Re: Grr, garbage collector, don't move my arrays!
Quote:
Originally Posted by TheCPUWizard
It won't work. He explicitly said he needs the object to remain pinned longer than the call into unmanaged land lasts. The array will be filled asynchronously.
The GCHandle class should do it alright.
-
Re: Grr, garbage collector, don't move my arrays!
Out of curiosity, what kind of C# application needs a block of memory in a fixed location? Even when considering IPC, you share memory blocks via system objects, not actual memory addresses.
-
Re: Grr, garbage collector, don't move my arrays!
You can still use the fixed statement (I do it all the time). you simply implement your architecture so that everything occurs as external method to the fixed statement.
GCHandle() will work, but can be difficult to properly handle under all exception conditions.
Also it is generally a really bad idea to pin memory for more than a very short time. Because of the way that the GC works internally, an existing pin effectively prevents GC of that generation entirely! :eek:
-
Re: Grr, garbage collector, don't move my arrays!
Quote:
Originally Posted by DeepT
Out of curiosity, what kind of C# application needs a block of memory in a fixed location? Even when considering IPC, you share memory blocks via system objects, not actual memory addresses.
A C# application that needs to call a native Windows function. If that function needs a buffer to read from, if you don't pin the memory, the garbage collector might move it and the native function trying to read it will fail.
A fixed statment works but I, personally, prefer not using unsafe code. Using a GCHandle is the managed way of doing it :)
-
Re: Grr, garbage collector, don't move my arrays!
Quote:
Originally Posted by riscutiavlad
A C# application that needs to call a native Windows function. If that function needs a buffer to read from, if you don't pin the memory, the garbage collector might move it and the native function trying to read it will fail.
A fixed statment works but I, personally, prefer not using unsafe code. Using a GCHandle is the managed way of doing it :)
I dont see how you equate the fixed statement with unsafe code.. :confused: :confused:
If you look at the fixed statement generated code, it actually creates a GCHandle and releases it inside a finally block so it is perfectly exception safe.
It is very similar to the lock statement in that it respect...
-
Re: Grr, garbage collector, don't move my arrays!
Well, for starters, because using the fixed statement requires an unsafe context.
-
Re: Grr, garbage collector, don't move my arrays!
Quote:
Originally Posted by TheCPUWizard
Also it is generally a really bad idea to pin memory for more than a very short time. Because of the way that the GC works internally, an existing pin effectively prevents GC of that generation entirely! :eek:
Really? Is that documented everywhere? It seems like a fairly serious limitation to have in a garbage collected language, especially one which prides itself on interop with unmanaged code.
If what you say is true, then all it would take to stop objects being collected would be a single pinned object in each generation. That's something which is pretty simple to do.