Memory Management Of Unmanaged Component By CLR - c#

I am having a little confusion , may be this question is very silly one.
where does the memory allocated for a unmanaged component?
In my .net code if i initiated an unmanaged component, where this component is going to be loaded and memory is allocated ?
How CLR marshall call between Managed and Unmanaged heap ?
EDIT
Thanks for your reply but what i am asking is say suppose i do a DLLIMPORT of User32.Dll , this is clearly a unmanaged dll and i call some function in User32.DLL now my question , how CLR marshall my call to this unmanged dll?

It starts out pretty easy. The pinvoke marshaller first calls LoadLibrary and passes the DLL name you specified, the DllImportAttribute.Value property. In your case, user32.dll is already loaded because it gets loaded by the .NET bootstrapper, its reference count just gets incremented. But normally the Windows loader gets the DLL mapped into the address space of the process so the exported functions can be called.
Next is GetProcAddress to get the address of the function to call, the DllImportAttribute.EntryPoint property. The marshaller makes a couple of tries unless you used ExactSpelling. A function name like "foo" is tested several possible ways, foo and fooW or fooA. Nasty implementation detail of Win32 related to the difference between Unicode and Ansi characters. The CharSet property matters here.
Now I need to wave hands a bit because it gets tricky. The marshaller constructs a stack frame, setting up the arguments that need to be passed to the exported function. This requires low level code, carefully excluded from prying eyes. Take it at face value that it performs the kind of translations that the Marshal class supports to convert between managed and unmanaged types. The DllImportAttribute.CallingConvention property matters here because that determines what argument value needs to be place where so that the called function can read it properly.
Next it sets up an SEH exception handler so that hardware exceptions raised by the called code can be caught and translated into a managed exception. The one that generates the more common one, AccessViolationException. And others.
Next, it pushes a special cookie on the stack to indicate that unmanaged code is about to start using stack. This prevents the garbage collector from blundering into unmanaged stack frames and interpret the pointers it finds there as managed object references. You can see this cookie back in the debugger's call stack, [Managed to Native Transition].
Next, just an indirect call to the function address as found with GetProcAddress(). That gets the unmanaged code running.
After the call, cleanup might need to be done to release memory that was allocated to pass the unmanaged arguments. The return value might need to be translated back to a managed value. And that's it, assuming nothing nasty happened, execution continues on the next managed code statement.

Unmanaged memory allocations come from the process heap. You are responsible for allocating/deallocating the memory, since it will not get garbage collected because the GC does not know about these objects.

Just as an academic piece of info expanding on what has been posted here:
There are about 8 different heaps that the CLR uses:
Loader Heap: contains CLR structures and the type system
High Frequency Heap: statics, MethodTables, FieldDescs, interface map
Low Frequency Heap: EEClass, ClassLoader and lookup tables
Stub Heap: stubs for CAS, COM wrappers, P/Invoke
Large Object Heap: memory allocations that require more than 85k bytes
GC Heap: user allocated heap memory private to the app
JIT Code Heap: memory allocated by mscoreee (Execution Engine) and the JIT compiler for managed code
Process/Base Heap: interop/unmanaged allocations, native memory, etc
HTH

Part of your question is answered by Michael. I answer the other part.
If CLR loaded into an unmanaged process, it is called CLR hosting. This usually involves calling an entry point in mscoree DLL and then the default AppDomain is loaded. In such a case, CLR asks for a block of memory from the process and when given, that becomes its memory space and will have a stack and heap.

Related

What are the managed stack and the managed heap?

MSDN's C# docs uses the terms stack and heap (eg. when talking about variable allocation).
It is stated that these terms means different memory spaces with well defined purposes (eg. local variables are always allocated in the stack whereas member variables of reference types are always allocated in the heap).
I understand what those terms mean in terms of certain CPU architecture and certain operating systems. Let's assume the x86-64 architecture, where the stack will be a per-thread contiguous memory block used to store call frames (local variables, return address, etc), and the heap being a one-per-process memory block for general purpose use.
What I do not understand yet is how those high-level and low-level definitions relate together.
I couldn't find an objective definition for the terms stack and heap in the MSDN docs, but I assume they mean something very similar to what those terms means in the x86-64 architecture.
For the purpose of this question, let's assume we are working on a custom device which the CPU and OS don't implement the concept of a separate stack and heap, they both (CPU/OS) deal directly with virtual memory. Will the stack and the heap (as cited in the MSDN docs) even exists in an .net application running on this particular device? If so, are they enforced by the CLR? Are they created on top of what the OS returns as allocated memory?
Operating Systems usualy handle memory as following:
The OS allocates the memory for global and static variables when it
loads the program into memory and doesn't deallocate it until the
program terminates. ... The other two regions, the stack and the heap,
are more dynamic - the memory is allocated and deallocated by the
program as needed. (Reference needed)
The "program" - in this case the CLR - allocates/requests memory on the stack or heap from the os when needed.
How does CLR manage this?
Managed Heap
The CLR implements an Managed Heap. This in fact is an abstraction over the native heap provided by the os:
The Managed Heap is used to divide the Heap in further segments (Large Object Heap, ObjectHeap for example).
When you allocate memory on the Managed Heap you won't get back a
real pointer as a return value. What you get instead is a Handle, which is a indirection to the "real" pointer. This is because the GC Collector can
compact your heap and move around the objects (allocated on native heap) and thus changing the pointer address)
If you want to allocate memory in the unmanaged heap you need to use
Marshal.AllocHGlobal or Marshal.AllocCoTaskMem
If code is blittable or you use the unsafe keyword you need to
pin the object so it doesent get moved around by GC. Because in both cases your referring to the object via the pointer directly and not the handle...
Managed Stack
This is used for stackwalking
Ref Counting, so the GC knows when he can move an object to the
next generation and so on...
So you see theres a level of abstraction over the native concepts provided by the os so it can be managed by the clr but the data at the end resides in the native stack/heap.
But what if the device/os doesn't provide a heap/stack (as stated per your question)?
CLR on a device/os without stack/heap
If the CLR would be made available on such an os without such memory segmentation, the CLR could be build seperately for that os (so it accepts the same IL and manages memory in a way it is efficient without the stack/heap).
In this case the documentation would change for such systems.
-OR-
It also could be possible that the clr creates their own datastructuers within the memory and manage its own stack and heap just to virtually comform the spezifications.
Remember the CLR is always Build separately for its destination (you dont use the same CLR Sourcecode and compile it once for linux and once for windows). Heck theres even an own CLR built in Javascript (.net blazor).
But since theres no such implementation nobody really can tell (what if questions are always tricky... What if I die tomorrow, what would I do today?). There are virtually no OS around that does not split their processes in Stack/heap.
Btw you stated following:
whereas member variables are always allocated in the heap
Thats not completely true if the object itself resides on the stack (eg. struct) then the members are also allocated on the stack.
A reference type always stores the pointer on the stack/heap (whereever the object resides of which it is member of) and points to an object in the heap. Local variables, eg. variables in methods, are always on the stack (value for valuetypes and pointer/handle for reference types)

C# Pinvoke IntPtr in structs and memory

If i have understood right, when using structs with non blitable values, the struct data from unmanaged memory is copied into the managed memory (basically having the same struct twice).
Also if im not wrong, IntPtr variables, are stored in managed memory, but the data they point to is in the unmanaged memory.
Now lets say i have a delegate method, which is being called by a c++ function and receives a struct as ref, and a handler would be something like:
private void _handler(ref MyStruct p){}
Now the api says I should not keep the reference to the struct as the memory might be recycled and used for further calls, but since the unmanaged struct is copied into managed memory, and after I assign it to a local variable it is copied again (because it is a struct!) i shouldnt have any issues at all if the unmanaged memory gets freed or re written.
However, if the struct contains an IntPtr variable, i might save a copy of the pointer but not of the data it points, so if i try to access the IntPtr data from my saved struct, i might get some memory fault, is this correct?
One last question is, doing changes to the struct in managed memory, will also affect the unmanaged memory struct, since it is passed by ref, and it implicitly means IN/OUT, so after the event handler call ends, changes in managed memory will be made in the unmanaged memory as well?
Your understanding is largely correct. Taking away the details of blittabiltiy, the root question is one of ownership of the memory being passed to your callback. Typically, the contract between the caller of the callback and the callback itself is that the memory is owned by the caller and will be valid only for the duration of the callback itself. (Other contracts are possible as well - for instance, the caller could transfer ownership of the memory to the callback, in which case the callback is responsible for freeing the memory when it is done).
In the documentation you reference, the API is telling you not to keep a reference to the memory, which means that you are very likely in the standard case where the caller owns the structure. What this means is that both the contents of the structure and everything pointed to by that structure should be valid during the call to your callback but cannot be relied upon after your callback completes.
Copying a structure to a local wouldn't be problematic because the native memory should not be freed until after your callback completes, so keeping as many copies as you need during the execution of the callback should be fine. What would be problematic is saving a copy of the structure to a location, such as a static field, which will be alive after your callback returns.
Since the structure is implicitly in/out, then modifications you make to it will be reflected on the native side of the call as well. This is true regardless of if the structure contained only blittable data. If the structure contained non-blittable data then the CLR would marshal your changes to the structure back out to the native copy when your code completes.
Note that just because you can modify the native structure does not mean that the API contract expects you to do so. Frequently API signatures contain pointers to structures in C++ in order to avoid copying the entire structure when making a call, not to enable modification of the structure.

Why is it called Marshal.AllocHGlobal if it allocates on the local heap?

From the MSDN documentation of Marshal.AllocHGlobal:
AllocHGlobal is one of two memory allocation methods in the Marshal class. This method exposes the Win32 LocalAlloc function from Kernel32.dll.
Considering there's a GlobalAlloc API which allocates memory on the global heap, rather than the local heap, isn't this method's name rather misleading?
Was there a reason for naming it AllocHGlobal, rather than AllocHLocal?
Update: Simon points out in the comments that there's no such thing as a global heap in Windows any more, and the GlobalAlloc and LocalAlloc APIs remained for legacy purposes only. These days, the GlobalAlloc API is nothing morethan a wrapper for LocalAlloc.
This explains why the API doesn't call GlobalAlloc at all, but it doesn't explain why the API was named AllocHGlobal when it doesn't (can't) use a global heap, nor does it even call GlobalAlloc. The naming cannot possibly be for legacy reasons, because it wasn't introduced until .NET 2.0, way after 16-bit support was dropped. So, the question remains: why is Marshal.AllocHGlobal so misleadingly named?
Suppose you're doing data transfer between apps using drag and drop or over the clipboard. To populate the STGMEDIUM structure you need an HGLOBAL. So you call AllocHGlobal. Hence the name.
The main use for this function is to interop with APIs that want an HGLOBAL. It would be confusing if it was called anything else because when you wanted an HGLOBAL you'd have to find some documentation to tell you that AllocAnythingElse produced a value you could use as an HGLOBAL.
This goes back to the olden days of Windows version 3. Back then there was a notion of a "default heap", the GlobalAlloc() api function allocated from it. Memory allocated from that heap could be shared between all processes.
That changed in the 32-bit version of Windows, processes can no longer share memory through a heap. Which made the terms "global heap" and "local heap" meaningless. There is still a notion of a default heap, the "process heap". GlobalAlloc() now allocates from that heap. But it can't be shared across process boundaries. The actual implementation of GlobalAlloc, and of Marshal.AllocHGlobal, uses the LocalAlloc() api function. Another Windows 3 holdover, somewhat more suitably named for what happens these days. It in turn uses HeapAlloc() with GetProcessHeap() on 32-bit Windows.
Agreeing on the heap to use is a significant interop concern. This very often goes wrong in poorly written C code that you pinvoke. Any such code that returns a pointer to allocated memory that needs to be released by the caller often fails due to memory leaks or access violations. Such C code allocates from its own heap with the malloc() function. Which is a private heap created by the C runtime library. You have no hope of releasing such memory, you don't know what heap was used and have no way to obtain the handle to the CRT heap.
This can only come to a good end when the C code uses a well-known heap. Like the process heap. Or CoTaskMemAlloc(), used by COM code. The other one in the Marshal class. Note that the pinvoke marshaller always releases memory when necessary with CoTaskMemFree(). That's a kaboom on Vista and up if that memory wasn't allocated with CoTaskMemAlloc(), a silent leak on XP.
I think you should read https://msdn.microsoft.com/en-us/library/ms810603.aspx
A short part of it:
Global and Local Memory Functions At first glance it appears that the
local and global memory management functions exist in Windows purely
for backward compatibility with Windows version 3.1. This may be true,
but the functions are managed as efficiently as the new heap functions
discussed below. In fact, porting an application from 16-bit Windows
does not necessarily include migrating from global and local memory
functions to heap memory functions. The global and local functions
offer the same basic capabilities (and then some) and are just as fast
to work with. If anything, they are probably more convenient to work
with because you do not have to keep track of a heap handle.
Nonetheless, the implementation of these functions is not the same as
it was for 16-bit Windows. 16-bit Windows had a global heap, and each
application had a local heap. Those two heap managers implemented the
global and local functions. Allocating memory via GlobalAlloc meant
retrieving a chunk of memory from the global heap, while LocalAlloc
allocated memory from the local heap. Windows now has a single heap
for both types of functions—the default heap described above.
Now you're probably wondering if there is any difference between the
local and global functions themselves. Well, the answer is no, they
are now the same. In fact, they are interchangeable. Memory allocated
via a call to LocalAlloc can be reallocated with GlobalReAlloc and
then locked by LocalLock. The following table lists the global and
local functions now available.
It seems redundant to have two sets of functions that perform exactly
the same, but that's where the backward compatibility comes in.
Whether you used the global or local functions in a 16-bit Windows
application before doesn't matter now—they are equally efficient.
etc...
Also memory was really expensive back in the days. Also have a look at the PostScript Language Reference Manual which might give you a good insight on usage of local/global memory.

Free managed memory allocation from unmanaged code

I'd like to do Marshal.AllocHGlobal in managed code, fill it with data, and pass that memory block to unmanaged (C++) code that will then be responsible for freeing it.
Under the hood, Marshal.AllocHGlobal calls LocalAlloc (and, I'm guessing, LocalLock). But in order for the unmanaged code to call LocalFree, it needs the HLOCAL returned by LocalAlloc, which Marshal.AllocHGlobal doesn't provide.
I'm not necessarily restricted to using AllocHGlobal; the high level goal is to let the managed code allocate memory that the unmanaged code and then read and free.
This is not a handle, not since Windows version 3. Calling LocalFree() on the pointer is fine, as the Windows SDK article shows in its example. Marshal.AllocCoTaskMem and CoTaskMemFree() are the better mouse trap here.

is it necessary to gchandle.alloc() each callback in a class?

I have a .NT class which has multiple delegates for callbacks from native code. Is it necessary to allocate all the delegates? I mean does GCHandle.Alloc() protects just the delegate or the entire class that owns the delegate from being collected?
A delegate has two relevant properties, Method and Target. The Target will be non-null if the delegate was created for an instance method. And that keeps the object alive, as long as the garbage collector can see the delegate instance.
Native code is relevant to having problems with callbacks. When you pass a delegate instance to a pinvoked native function then the P/Invoke marshaller will use Marshal.GetFunctionPointerForDelegate() to create a little stub that produces the required Target reference when the native code makes the callback. The garbage collector however can not see this stub and therefore won't find a reference to the delegate object. And collects it. The next callback from the native code produces a crash.
To avoid this, you must store the delegate object yourself so that it stays referenced for as long as the native code can make the callback. Storing it in a static variable is an obvious solution.
I am wrong.
You don't need to pinned the delegate (at the other hand, you cannot pinned the delegate, there will be a exception be thrown (System.ArgumentException: Object contains non-primitive or non-blittable data.)
reference:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/bd662199-d150-4fbf-a5ee-7a06af0493bb/interop-pinning-and-delegates?forum=
Details about that in Chris Brumme's blog http://blogs.msdn.com/cbrumme/archive/2003/05/06/51385.aspx
Chris Brumme wrote:
Along the same lines, 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 haven’t started using Customer Debug Probes during development, please take a look!
I think there will be something wrong happened (but not usually) when you just store the delegate object.
As we all know , the managed memory will be arranged by Garbage Collect. ( That means the physical memory address of a managed object will be changed. )
Imaging there is a long-time-life delegate to be called by native code, we set the delegate as the static member or class member . But sometime (we don't know when , we just know it will happen) , GC arranged memory, and the physical memory of the delegate may from 0x000000A to 0x0000010 . But the native code know nothing about it , for the native code , it only knows to call at 0x000000A forever.
So we should not only store the delegate object but also use GCHandle.Alloc to tell GC not move the physical memory of the delegate object. Then the native code will do well at callback time.
Well , because the GC do not arrange managed memory frequencly , so for a short-time-life delegate , even you do not call the GCHandle.Alloc , your codes always "DO WELL" , but sometimes it will mad.
Now , you know the reason.
reference:
http://dotnet.dzone.com/news/net-memory-control-use-gchandl

Categories