Will using GetComInterfaceForObject and passing the returned IntPtr to unmanaged code keep the managed object from being moved in memory? Or does the clr somehow maintain that ptr? Note that the unmanaged code will use this for the lifetime of the program, and I need to make sure the managed object is not being moved by the GC.(At least I think that's right?)
EDIT - Alright I found some info and I am thinking that this may be the answer. It deals with delegates, but I would have to believe calling GetComInterfaceForObject does something along the same lines.
Source of the Following text
"Managed Delegates can be marshaled to unmanaged code,
where they are exposed as unmanaged function pointers. Calls on those
pointers will perform an unmanaged to managed transition; a change in
calling convention; entry into the correct AppDomain; and any necessary
argument marshaling. Clearly the unmanaged function pointer must refer to a
fixed address. It would be a disaster if the GC were relocating that! This
leads many applications to create a pinning handle for the delegate. This
is completely unnecessary. The unmanaged function pointer actually refers
to a native code stub that we dynamically generate to perform the transition
& marshaling. This stub exists in fixed memory outside of the GC heap.
However, the application is responsible for somehow extending the lifetime
of the delegate until no more calls will occur from unmanaged code. The
lifetime of the native code stub is directly related to the lifetime of the
delegate. Once the delegate is collected, subsequent calls via the
unmanaged function pointer will crash or otherwise corrupt the process. In
our recent release, we added a Customer Debug Probe which allows you to
cleanly detect this all too common bug in your code. If you havent
started using Customer Debug Probes during development, please take a look!"
As your edit states (about delegates), your managed object doesn't need to be pinned, since GetComInterfaceForObject returns a "pinned" pointer that calls through to the correct managed object. However, you will need to make sure that the managed object lives for as long as the COM clients are using the unmanaged pointer to it.
Related
What I am trying to understand is when I am creating my own classes, how do I know what is a managed vs unmanaged resource so I know if my class needs to provide the ability to clean it up or if GC will eventually do it. Also, going a little deeper, when I create a .Dispose() method there will be a block for managed resources and a block for unmanaged resources and how do I know which resources should get cleaned up in which block.
I have read many answers about managed vs unmanaged resources in a C# program but most of them are providing the definition with regards to GC cleanup as in "managed resource are cleaned up by GC and unmanaged resources are not". That doesn't help me because I can't see how GC determines what it will clean up and what it will leave behind. I also understand that if a class provides a .Dispose() method that my program should execute it.
I have seen answers stating that if I use a WIN32 API, I've created an unmanaged resource. If I don't call a WIN32 API, does that mean I don't have any unmanaged resources? I've also stumbled over Marshall. Does Marshall also create unmanaged resources? Are there other "keywords / classes" to use to identify that I'm creating unmanaged resources?
Please exclude from your answers anything about "managed resources that are tying up huge amounts of memory". I understand that it would be nice to give the ability to free up this memory but it is not a requirement as the GC will eventually do it, just not always in a timely manner.
Usually if you are not crossing the boundaries of native and managed codes you don't have to bother about releasing unmanaged resources in your classes.
When you are running your .NET application, the framework allocates a managed slice in the memory for it, where almost everything that you can access from the .NET framework will be stored and tracked by the GC. Everything else falls outside of this slice, left without the sharp eye of the GC.
So for your question about how the GC determines which resources should be collected and which not, the short answer is that it doesn't know anything about unmanaged resources, so it also does not able to collect them.
These worlds - the native and the managed - are separated but they can communicate with eachother and thats what Marshalling is for. You can read more about it here. With that of course you can create unmanaged resources but that does not mean that you will do every time when you are using it.
It's also a bit extreme to say that every time you are using Win32 APIs you will create native resources that you must release.
When you use Platform Invoke or C++/CLI wrapper calls on any native code which creates pointers or anything which should be released by hand in the native world (those of course are not tracked by the GC), you have to release them manually if they are not released already by the native side. But if you use APIs that just works with primitive types then you don't have to release anything.
If you are not using anything from above then there is a good chance that you don't have to prepare your classes for directly release anything unmanaged.
There are types using native resources - you probably already came accross - which are managed wrappers under the hood. They release those resources in their Dispose implementation with marshalling.
For example the FileStream managed class is holding an unmanaged handle to the given file. The FileStream itself is a managed class tracked and collected by the GC, but the unmanaged handle is not, it must be released manually, so if you, the user of the FileStream are not calling its Dispose method in your code, that handle will remain in the memory leaking until the application exits.
I try to build a little tensorflow application with TensorFlowSharp and sometimes I recieve this exception:
Managed Debugging Assistant 'CallbackOnCollectedDelegate'
For the function TensorFlowSharp!TensorFlow.TFBuffer+BufferReleaseFunc::Invoke
I tried to find out what it means but I didn't fully understand the explanations. This is the part of the code where the exception is thrown:
var graph = new TFGraph();
var model = File.ReadAllBytes(ModelsFile);
graph.Import(model, "");
Does somebody know what I should do to prevent this exception?
Bruno
I assume this is a bug in TensorflowSharp.
The error looks like a usually inconsistent access violation in the CLR code (occurs usually only under heavy load or on a random number of attempts). Citing from Microsoft docs:
The callbackOnCollectedDelegate managed debugging assistant (MDA) is
activated if a delegate is marshaled from managed to unmanaged code as
a function pointer and a callback is placed on that function pointer
after the delegate has been garbage collected.
This type of error occurs when a delegate from which the function pointer was created and exposed to unmanaged code was garbage collected. When the unmanaged component tries to call on the function pointer, it generates an access violation. The failure appears random because it depends on when garbage collection occurs.
The resolution can be difficult, since once a delegate has been marshaled out as an unmanaged function pointer, the garbage collector cannot track its lifetime. Instead, it is required to keep a reference to the delegate for the lifetime of the unmanaged function pointer. In order to do this, the faulty delegate that was collected, has to be identified in TensorFlowShapr's code (or your code).
You can also enable the gcUnmanagedToManaged MDA to force a garbage
collection before every callback into the runtime. This will remove
the uncertainty introduced by the garbage collection by ensuring that
a garbage collection always occurs before the callback. Once you know
what delegate was collected, change your code to keep a reference to
that delegate on the managed side for the lifetime of the marshaled
unmanaged function pointer.
So, I guess it's best to report this to the maker of the library.
I see only one good candidate for this bug, a delegate in Buffer.cs. But Miguel already fixed this bug on July 27th, the diff is here. So just make sure to update your copy. If you obtained it from Nuget then ensure you have at least version 1.30
I am working with some C# and C++ unmanaged code and there are two things I don't understand when dealing with memory. If someone can help me understand:
If a variable is dynamically allocated under C# (using new) and then is passed to the C++ unmanaged code. Does that variable memory needs to be deallocated manually under the C++ unmanaged code by the user ?
If a variable is dynamically allocated under C++ unmanaged (using new) and then passed to C#, is it safe to say the Garbage Collector will deallocate that memory ?
No, since the object is allocated on managed heap GC will handle deallocation as usual. The problem is you must tell him not to deallocate or change address of the object while it is used from unmanaged code because GC can't know how long you are going to use the object from the unmanaged code. This can be done by PINNING the object.
See answer to this question.
No, since the object is allocated on C++ unmanaged heap GC won't touch it. You have to deallocate it yourself using delete.
Edit:
If you need to allocate an object in managed code and deallocate in unmanaged code or vice versa, It's good to know there is OS heap for this purpose that you can use via Marshal.AllocHGlobal and Marshal.FreeHGlobal calls from C#, there will be similar calls in C++.
It's really simple!
Depends
Depends
Eh, Sorry about that.
Under typical conditions, C# will keep track of the memory and get rid of it any time after it's no longer used on the C# side. It has no way of tracking references on the C++ side, so one common mistake in interop is that the memory is deallocated before the unmanaged side is done with it (resulting in loads of FUN). This only applies for cases where the memory is directly referenced, not when its copied (the typical case being a byte[] that's pinned for the duration of the unmanaged call). Don't use automatic marshalling when the life-time of the object/pointer being passed to unmanaged code is supposed to be longer than the run of the invoked method.
Under typical conditions, C# has no way of tracking memory allocations in the C++ code, so you can't rely on automatic memory management. There are exceptions (e.g. some COM scenarios), but you'll almost always need to manage the memory manually. This usually means sending the pointer back to the C++ code to do the deallocation, unless it used a global allocator of some kind (e.g. CoMemoryInitialize). Remember that in the unmanaged world, there is no one memory manager that you can safely invoke to dispose of memory; you don't really have the necessary information anyway.
This only applies to pointers, of course. Passing integers is perfectly fine, and using automatic marshalling usually means the marshaller takes care of most of the subtleties (though still only in the simplest case, so be careful). Unmanaged code is unmanaged - you need to understand perfectly how the memory is allocated, and how, when and who is responsible for cleaning up the memory.
As a rule of thumb, whichever component/object allocates memory should deallocate memory. For every new a delete by the one which did new.
That is the ideal. If not followed for reasons such as you C++ program may terminate and not exists when allocated memory's lifecycle comes to an end, your C# should clean up and visa versa.
I tried to find out how pinned pointers defined with fixed keyword work. My idea was that internally GCHandle.Alloc(object, GCHandleType.Pinned) was used for that. But when I looked into the IL generated for the following C# code:
unsafe static void f1()
{
var arr = new MyObject[10];
fixed(MyObject * aptr = &arr[0])
{
Console.WriteLine(*aptr);
}
}
I couldn't find any traces of GCHandle.
The only hint I saw that the pinned pointer was used in the method was the following IL declaration:
.locals init ([0] valuetype TestPointerPinning.MyObject[] arr,
[1] valuetype TestPointerPinning.MyObject& pinned aptr)
So the pointer was declared as pinned, and that did not require any additional methods calls, to pin it.
My questions are
Is there any difference between using pinned pointers in the declaration and pinning the pointer by using GCHandle class?
Is there any way to declare a pinned pointer in C# without using fixed keyword? I need this to pin a bunch of pointers within a loop and there's no way I can do this using fixed keyword.
Well, sure there's a difference, you saw it. The CLR supports more than one way to pin an object. Only the GCHandleType.Pinned method is directly exposed to user code. But there are others, like "async pinned handles", a feature that keeps I/O buffers pinned while a driver performs an overlapped I/O operation. And the one that the fixed keyword uses, it doesn't use an explicit handle or method call at all. These extra ways were added to make unpinning the objects again as quick and reliable as possible, very important to GC health.
Fixed buffer pins are implemented by the jitter. Which performs two important jobs when it translates MSIL to machine code, the highly visible one is the machine code itself, you can easily see it with the debugger. But it also generates a data structure used by the garbage collector, completely invisible in the debugger. Required by the GC to reliably find object references back that are stored in the stack frame or a CPU register. More about that data structure in this answer.
The jitter uses the [pinned] attribute on the variable declaration in the metadata to set a bit in that data structure, indicating that the object that's referenced by the variable is temporarily pinned. The GC sees this and knows to not move the object. Very efficient because it doesn't require an explicit method call to allocate the handle and doesn't require any storage.
But no, these tricks are not available otherwise to C# code, you really do need to use the fixed keyword in your code. Or GCHandle.Alloc(). If you are finding yourself getting lost in the pins then high odds that you ought to be considering pinvoke or C++/CLI so you can easily call native code. The temporary pins that the pinvoke marshaller uses to keep objects stable while the native code is running are another example of automatic pinning that doesn't require explicit code.
what if I had a native C++ function in which, depending on the result of the function, the responsibility of deleting a certain pointer (delete[]) differs between the caller and the function. I would of course check for the return value and act accordingly in C++.
Question is, what if the function was marshalled between C++ and C#, will setting the pointer to null in C# be enough?
No. C# can't do what delete[] in C++ does. You'd have to use a shared memory allocation API, or write a C++ wrapper that handles the cleanup.
No, simply setting a pointer allocated in native code to null will not free the memory. The CLR can only garbage collect memory that it knows about (aka managed memory). It has no idea about native memory and hence can't collect it. Any native memory which has ownership in a managed type must be explicitly freed.
The most common way this is done is via the Alloc and Free functions on the Marshal class
http://msdn.microsoft.com/en-us/library/atxe881w.aspx