Which takes a struct and gives me back an IntPtr to it. I use it as such:. If not, is there a way I can wrap the call to SDL. Yes, C will not automatically free memory allocated by Marshal. That memory must be freed with a call to Marshal. FreeHGlobal or else it will be leaked. Using this wrapper you can either manually free the memory by wrapping the object in a using statement or by allowing it to be freed when the finalizer runs.
A lot of people don't know this and that's why you got so many answers saying you can't , but there is something built in to. NET just for things like that: SafeHandle. In fact, the. NET 2. If you want deterministic cleanup instead of just waiting for the finalizer to get around to it you will need to either call Close or Dispose explicitly. Once you do that your original Copy example will work exactly like you expected it to. When the two pointers go out of scope and are finalized they will be cleaned up afterwards.
He goes into depth on how to properly write your own SafeHandles in the article. Yes, you have to Free it, and the way you have got it as your 6 line program is pretty efficient. Its the tradeoff you make when stepping outside the garbage collector. Unfortunately there's no built-in automatic way to do this. If you call AllocHGlobal , you must explicitly free it with FreeHGlobal unless you are okay with potentially massive memory leaks. So you call AllocHGlobal. Hence the name. 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 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. 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. The other one in the Marshal class. Note that the pinvoke marshaller always releases memory when necessary with CoTaskMemFree. 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. This may be true, but the functions are managed as efficiently as the new heap functions discussed below.
In fact, porting an application from 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.
The unmanaged function can now modify the array elements, and they will be marshaled back to the caller. The unmanaged function cannot, however, change the size of the array. The pnElements parameter is also a pointer, which lets the function pass back the number of elements that ppArray points to.
When youre using Platform Invoke to execute such a function, the first parameter has to be represented by an IntPtr because. NET marshaling cannot deal with pointers that have more than one level of indirection:. Note how the ref keyword is used to show that the parameters are being passed by reference. To use this function, you have to marshal the data manually to copy the data into unmanaged memory and create the IntPtr needed for the first argument.
You also need to marshal the data back into managed memory after the call because Platform Invoke does not know how to deal with the IntPtr :. AllocHGlobal allocates unmanaged memory on the Windows heap. The argument is the number of bytes to allocate, and the Marshal.
SizeOf function can be used to find the size of a managed type or object. Copy is used to copy the data between managed and unmanaged memory.
When the call has been made, the DLL function might have passed back a different buffer, so we need to create a new managed array and copy the data back from unmanaged memory. After copying, the unmanaged memory can be released. If a DLL function allocates memory, you will need to know which mechanism it is using.
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. 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. 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. 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.
0コメント