C# deallocate memory referenced by IntPtr - c#

I am using some unmanaged code that is returning pointers (IntPtr) to large image objects. I use the references but after I am finished with the images, I need to free that memory referenced by the pointers. Currently, the only thing that frees the memory is to shutdown my entire app. I need to be able to free that memory from inside my application.
Here is the call to that allocates the memory. hbitmap is the pointer that is returned and needs to be deallocated.
[DllImport("twain_32.dll", EntryPoint = "#1")]
public static extern TwainResult DsImageTransfer(
[In, Out] Identity origin, [In] Identity dest, DataGroup dg,
DataArgumentType dat, Message msg, ref IntPtr hbitmap);

You need to use the specific memory allocator mechanism that was used to allocate the memory in the first place.
So, if you were using COM and the IMalloc interface to allocate the memory, then you have to pass the IntPtr back to the Free method on that implementation in order to free the memory allocated.
If you are indeed using the COM allocator that is returned by a call to CoGetMalloc, then you can call the static FreeCoTaskMem method on the Marshal class.
The Marshal class also has a method for freeing memory that is allocated through a call to LocalAlloc called FreeHGlobal.
However, and this is a common case, if the memory was allocated by the new operator in C++, or a call to malloc in C, then you have to expose a function in unmanaged code through interop which will free the memory appropriately.
In the case of C++, you would expose a function that takes a pointer and simply calls delete on that pointer. In the case of malloc, you would create a function that takes a pointer, and calls free on that pointer.
In specific regards to your question, it would seem that DsImageTransfer is a vendor-specific API (one that doesn't have much discoverability on the web either, I'm afraid), so more information is needed about that specific API function and how it allocates memory. Just knowing the handle type (an HBITMAP in this case) doesn't give any indication as to how it's allocated. It can be allocated with all the mechanisms mentioned above.
Assuming it is creating the HBITMAP using GDI Object api functions (specifically, the CreateBitmap function), then you could use the DeleteObject function to release the handle (as per the documentation page for the GDI Object API functions).

That would depend on how that memory was allocated. The Marshal class has methods for deallocating memory allocated through the common interop allocation patterns, like FreeCoTaskMem. If the unmanaged code uses a non Interop compatible way of allocating, then you cannot interop with it.
Updated
If I would venture a guess, the function #1 you invoke in twain_32.dll is the DS_ENTRY function in a TWAIN provider. The Twain specifications call out the memory resource management protocol:
Memory Management in TWAIN 2.0 and
Higher
TWAIN requires Applications and
Sources to manage each other’s memory.
The chief problem is guaranteeing
agreement on the API’s to use. TWAIN
2.0 introduces four new functions that are obtained from the Source Manager
through DAT_ENTRYPOINT.
TW_HANDLE PASCAL DSM_MemAllocate (TW_UINT32)
PASCAL DSM_MemFree (TW_HANDLE)
TW_MEMREF PASCAL DSM_MemLock(TW_HANDLE)
void PASCAL DSM_MemUnlock(TW_HANDLE)
These functions correspond to the
WIN32 Global Memory functions
mentioned in previous versions of the
TWAIN Specification: GlobalAlloc,
GlobalFree, GlobalLock, GlobalUnlock
On MacOS/X these functions call
NewPtrClear and DisposePtr. The lock
and unlock functions are no-ops, but
they still must be called. TWAIN 2.0
compliant Applications and Sources
must use these calls on all platforms
(Windows, MacOS/X and Linux). The
Source Manager takes the
responsibility to make sure that all
components are using the same memory
management API’s.
So to free resources you're supposed to call DSM_MemFree, which supposedly on Win32 platforms would be implemented through GlobalFree, or Marshal.FreeHGlobal.
Since this is mostly speculation on my part, you better validate with the specs of the specific TWAIN implementation you use.

It depends. Do you have any documentation (or source code) for the native functions you are calling?
Native code doesn't have a single deallocation function. This is one of the great advantages of the CLR.
If I was a betting man, I'd go for GlobalFree. But it's not going to be much fun trying various APIs until your code stops crashing.

Please show your unmanaged code. There are different ways to allocate memory in unmanaged land, and you must use the correct corresponding means of deallocating. You will probably end up implementing a Finalizer and IDisposable, and implementing the Dispose pattern as described here: http://www.codeproject.com/KB/cs/idisposable.aspx

Perhaps you could try creating a Bitmap object from hBitmap and then disposing it.
Bitmap bitmap = Bitmap.FromHBitmap(hBitmap);
bitmap.Dispose();

As everyone else is pointing out, It dpends on how it was allocated. However, if it really is a Win32 hbitmap, then you deallocate it with the Win32 "DeleteObject" function.

Related

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.

Convention for passing BSTRs into COM functions from C# (COM interop)

I am writing writing an API in COM in C++, and also writing a program which consumes this API in C#. My question is about BSTR memory management semantics when passing BSTRs into COM functions. Say my IDL looks like:
HRESULT SomeFunction([in] BSTR input);
Currently this function is implemented like this:
HRESULT SomeFunction(BSTR input) {
// Do stuff ..., then:
SysFreeString(input);
}
When I call it from C# with something like SomeFunction(myString), will C# generate something like this (pseudocode):
myString = SysAllocString("string");
SomeFunction(myString);
Or rather like this:
myString = SysAllocString("string");
SomeFunction(myString);
SysFreeString(myString);
That is, does C# free the BSTR that it generates to marshal to the COM interface, or should I free it inside my function? Thanks!
From Allocating and Releasing Memory for a BSTR:
When you call into a function that expects a BSTR argument, you
must allocate the memory for the BSTR before the call and
release it afterwards. ...
So don't free it if it is an input parameter. C# (and any other runtime that uses COM objects) must respect the COM convention for managing memory pass in and out of COM objects, and must therefore manage the memory for the string if it is an input parameter. Otherwise, how would a COM object know that it is being called from C# or some other language runtime?
Additional google-fu turned up this: Marshaling between Managed and Unmanaged Code
... Regarding ownership issues, the CLR follows COM-style
conventions:
Memory passed as [in] is owned by the caller and should be both
allocated by the caller and freed by the caller. The callee should
not try to free or modify that memory.
Memory allocated by the callee and passed as [out] or returned
is owned by the caller and should be freed by the caller.
The callee can free memory passed as [in, out] from the caller,
allocate new memory for it, and overwrite the old pointer value,
thereby passing it out. The new memory is owned by the caller. This
requires two levels of indirection, such as char **.
In the interop world, caller/callee becomes CLR/native code. The rules
above imply that in the unpinned case, if when in native code you
receive a pointer to a block of memory passed to you as [out] from
the CLR, you need to free it. On the other hand, if the CLR receives
a pointer that is passed as [out] from native code, the CLR needs to
free it. Clearly, in the first case, native code needs to do the
de-allocation and in the second case, managed code needs to do
de-allocation.
So the CLR follows the COM rules for memory ownership. QED.
Do you mean from the point of view of the C# developer or from the C++ developer.
The C# developer should not have to worry about any memory management when dealing with COM+.
Creating a COM+ component in C++, you would not have to know who is calling you, the memory semantics are the same. If it's an in parameter, the caller is responsible for managing the memory, regardless of whether it's C++ or C#. In C#, the CLR takes care of it for them.

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.

Clean Unmanaged memory

Whenever i use one function from unmanaged dll in Usercontrol, I got this error.
"System.AccessViolationException: Attempted to read or write protected memory. This is often a indication that other memory is corrupt." But it only happens if I use this function so many times. But I need to use this function every 3 minutes. Any ideas is much appreciated.Thank you.
From what you've posted with very little information my first gut response would be that the unmanaged dll your using if it was written by a 3rd party has memory handling faults inside it. If it's an included windows DLL you need to do more research on how your using it, or the into the resources its using as this error is most likely caused by your code if it's a windows DLL.
One thing you should look into is how your accessing shared data between your program and the external DLL, perhaps some of your members need to be marked volatile and use locking when handling them.
Memory Management on Marshalling is a hard thing. You give very less information so i only can answer in general:
Te Interop marshaller use CoTaskMemFree and CoTaskMemAlloc to alloc memory. If your DLL allocates memory, and .NEt should free it (or vice versa) you have to use this functions. If the memory is allocated by new or malloc() and freed by delete or free() the library must provide some Cleanup() function to deal with this. To prevent the Marshaller from freeing memory, you must declare your functions with IntPtr as parameter / return value data type instead of using string or whatever else.
Consider this declarations:
[ DllImport( "Your.dll", CharSet=CharSet.Auto )]
public static extern string GetSomeString();
[ DllImport( "Your.dll", CharSet=CharSet.Auto )]
public static extern IntPtr GetSomeString();
The first function must return a string allocated with CoTaskMemAlloc() and it is freed by the .NET Marshaller. The second function can return a string allocated by malloc or delete, but the memory is not freed automatically. You must call some kind of FreeMemory(IntPtr) function, which the library must provide.
Don't forget to read:
.NET Default Marshaling Behavior

Marshal.AllocHGlobal VS Marshal.AllocCoTaskMem, Marshal.SizeOf VS sizeof()

I have the following struct:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct WAVEHDR
{
internal IntPtr lpData; // pointer to locked data buffer
internal uint dwBufferLength; // length of data buffer
internal uint dwBytesRecorded; // used for input only
internal IntPtr dwUser; // for client's use
internal uint dwFlags; // assorted flags (see defines)
internal uint dwLoops; // loop control counter
internal IntPtr lpNext; // reserved for driver
internal IntPtr reserved; // reserved for driver
}
I need to allocate unmanaged memory to store an instance of above struct. A pointer to this struct will be passed to waveOut win32 api functions (waveOutPrepareHeader, waveOutWrite, waveOutUnprepareHeader).
Should I use Marshal.AllocHGlobal() or Marshal.AllocCoTaskMem()? What is the difference?
Should I pass sizeof(WAVEHDR) or Marshal.SizeOf(typeof(WAVEHDR)) to the memory allocation method? What is the difference?
NOTE that the allocated memory must be pinned.
A Windows program always has at least two heaps in which unmanaged memory is allocated. First is the default process heap, used by Windows when it needs to allocate memory on behalf of the program. The second is a heap used by the COM infrastructure to allocate. The .NET P/Invoke marshaller assumes this heap was used by any unmanaged code whose function signature requires de-allocating memory.
AllocHGlobal allocates from the process heap, AllocCoTaskMem allocates from the COM heap.
Whenever you write unmanaged interop code, you should always avoid a situation where code that allocates unmanaged memory is not the same as the code that frees it. There would be a good chance that the wrong de-allocator is used. This is especially true for any code that interops with a C/C++ program. Such programs have their own allocator that uses its own heap, created by the CRT at startup. De-allocating such memory in other code is impossible, you can't reliably get the heap handle. This is a very common source of P/Invoke trouble, especially because the HeapFree() function in XP and earlier silently ignore requests to free memory that wasn't allocated in the right heap (leaking the allocated memory) but Vista and Win7 crash the program with an exception.
No need to worry about this in your case, the mmsystem API functions you are using are clean. They were designed to ensure the same code that allocates also deallocates. This is one reason you have to call waveInPrepareHeader(), it allocates buffers with the same code that ultimately deallocates them. Probably with the default process heap.
You only need to allocate the WAVEHDR structure. And you are responsible for releasing it when you're done with it. The mmsystem APIs don't do it for you, most of all because they cannot do so reliably. Accordingly, you can use either allocator, you just need to make sure to call the corresponding free method. All Windows APIs work this way. I use CoTaskMemAlloc() but there really isn't a preference. Just that if I'm calling badly designed code, it is slightly likelier to use the COM heap.
You should never use sizeof() in an interop scenario. It returns the managed size of value type. That might not be the same after the P/Invoke marshaller has translated a structure type according to the [StructLayout] and [MarshalAs] directives. Only Marshal.SizeOf() gives you a guaranteed correct value.
UPDATE: there was a big change in VS2012. The C runtime library included with it now allocates from the default process heap instead of using its own heap. Long term, that makes AllocHGlobal the most likely avenue for success.
1) Marshal.AllocHGlobal will work for sure. Based on the docs for Marshal.AllocCoTaskMem, Marshal.AllocCoTaskMem should work too.
2) Use Marshal.SizeOf(typeof(WAVEHDR)). Although you can use the Marshal.SizeOf method, the value returned by this method is not always the same as the value returned by sizeof. Marshal.SizeOf returns the size after the type has been marshaled, whereas sizeof returns the size as it has been allocated by the common language runtime, including any padding.
2) As far as I know the sizeof can only be used with types that have a predefined size at the compile-time.
So use Marshal.SizeOf(typeof(WAVEHDR)).

Categories