I have a service that's using ASP WebApi. Each http request translates to a thread that needs to do some data manipulation (possibly changing the data). The API layer is written in C# and the data manipulation is written in C++. The C# layer calls the native library and supplies a pointer to some managed buffer.
Couple of questions:
How can I make sure there are no races? is std::mutex in the native library enough in this case? (do managed threads map to native threads? will they share the same std::mutex?)
How can I make sure that the GC doesn't release the pointer to the managed buffer while the native library is manipulating it?
Do you need a shared buffer? If the buffer is only ever used on one thread, you save yourself a lot of trouble. Managed threads do not map to native threads 1:1, but I'm not sure if that has any effect on your scenario.
You need to fix the buffer, and keep it fixed the whole time the native code has a pointer to it - releasing is the least of your worries, the .NET memory is moved around all the time. This is done using the fixed block.
Fixing managed memory:
byte[] theBuffer = new byte[256];
fixed (byte* ptr = &theBuffer[0])
{
// The pointer is now fixed - the GC is prohibited from moving the memory
TheNativeFunction(ptr);
}
// Unfixed again
However, note that prohibiting the GC from moving memory around can cause you quite a bit of trouble - it can prevent heap compaction altogether in a high-throughput server, for example.
If you don't need to work with the memory in the managed environment, you can simply allocate unmanaged memory for the task, such as by using Marshal.AllocHGlobal.
Related
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'm using locked bitmaps a lot recently, and I keep getting "attempted to access invalid memory" errors. This is mostly because the bitmap has been moved in memory. Some people using GCHandle.Alloc() to allocate memory in the CLR and pin it. Does Bitmap.LockBits() do the same? I don't understand the difference between "locking" memory and "pinning" memory. Can you also explain the terminology and the differences if any?
GCHandle.Alloc is a more generic method, that allows you to allocate a handle to any managed object and pin it in memory (or not). Pinning memory prevents GC from moving it around, which is especially useful when you have to pass some data, for example an array, to a unmanaged code.
GCHandle.Alloc will not help you access bitmap's data in any way, because pinning this object will just prevent the managed object from moving around (the Bitmap object) (and being garbage collected).
Bitmap however is a wrapper around native GDI+'s BITMAP structure. It doesn't keep data in any managed array that you would have to pin, it just managed a native handle to GDI+ bitmap object. Because of that Bitmap.LockBits is a way of telling this bitmap that you are interested in accessing it's memory, and it's just a wrapper around GdipBitmapLockBits function. So your need of calling it has more to do with the fact that you are working with GDI+ bitmaps than with the fact, that you're working in managed environment with GC.
Once you have used LockBits you should be able to access it's memory using pointers through BitmapData.Scan0 - it's an address of first byte of data. You should not have problems as long, as you do not access memory behind BitmapData.Scan0 + Height * Stride.
And rememberto UnlockBits when you are done.
In your case an attempted to access invalid memory error is most probably caused by invalid memory allocation which you are doing in the unsafe part of code, e.g allocated array is smaller than number of pixels you are trying to put in that.
There is also no need to think about pinning the objects unless your image data is less than 85000 Bytes as only objects less than 85K will be moved in memory.
Another story would be if you pass the object to unmanaged code, for example in the c++ library for faster processing. In this case your exception is very possible if the passed image gets out of scope and will be garbage collected. In this case you can use GCHandle.Alloc(imageArray,GCHandleType.Pinned); and than call Free if you do not need it any longer.
there's a WinForms-application written in C# using .NET Framework 3.5. This application uses a C++ Dll which is imported using the following declaration:
[DllImport(DllName)]
public static unsafe extern int LoadDBData(String dsn, String userid, String password);
This method imports data from a given ODBC-DSN using a SQL Server database. The call crashes when there is too much data in database. The provider of this extern dll said this happens because the dll is unable to grab more heap size and my application should provide more heap memory.
How could I solve this problem? As far as I know the only possibility to exclude a component from automatic garbage collection is the unsafe keyword which I already used.
Any idea would be appreciated.
Thanks in advance
Martin
This seems like a problem with the vendor's library, rather than your code.
Managed and unmanaged memory should be considered to be completely separate. Managed memory is typically memory allocated on a garbage-collected
heap, while unmanaged memory is anything else: the ANSI C memory pool
allocated through malloc(3), custom memory pools, and
garbage-allocated heaps outside the control of the CLI implementation...
Note that the above quote is from the Mono documentation, but I believe (if I'm not mistaken) the same is true for .NET in general. If the data is being loaded in the DLL's internal data structures, then it should allocate its own memory. If you're providing a buffer which will get filled up with the data, then it will only get filled up with as much data as you've allocated for the buffer (and pinned before marshalling). So where is the data being loaded?
You can't increase the heap size in .NET.
You could create an EXE in c/c++ that your .NET app calls using Process.Start.
Your c/c++ EXE would just call the DLL function and return the result (or if you have more than one function it could take a command line parameter). If you don't want a separate EXE you could try using RunDll32 instead.
I doubt this is specific to .NET, managed memory, garbage collection etc. It's a native DLL so it uses regular, unmanaged memory. Of course, the .NET runtime will also use it's share of memory but a native application using the DLL would do the same.
If you're running in a 32 bit process, the total heap size for .NET and unmanaged code can be limited to 1.5 GB. It's difficult to tell without additional information, but you might have hit that limit.
So one option would be to ask your vendor, whether they have a 64 bit version of the library and switch to a 64 process. In a 64 bit process, memory is almost unlimited (according to today's standard).
I have an unmanaged method that when executed takes high CPU. Is it safe to say that unmanaged calls naturally take high CPU?
Following is the code:
public void ReadAt(long ulOffset, IntPtr pv, int cb, out UIntPtr pcbRead)
{
Marshal.Copy(buffer, 0, pv, bytesRead);
pcbRead = new UIntPtr((uint)bytesRead);
bytesRead = 0;
if (streamClosed)
buffer = null;
}
No it's not safe to generalize this. Both managed and unmanaged methods take whatever CPU they need to execute their code.
When someone says unmanaged calls may be expensive they usually mean the overhead from switching between managed and unmanaged. This particular cost will only matter if you do unmanaged calls in tight loops like per-pixel processing on a large image.
Some of the overhead of unmanaged calls can be removed by proper attributes, in particular it is possible to move the security checks from per-call to assembly-load-time. This is of course already done for all unmanaged functions in the .NET framework.
The best guess (without more context) about why you are spending so much time in that function is that you are either (a) copying a very large array or (b) you are calling the method very often in a loop.
In the first case the overhead from switching between managed-unmanaged for Marshal.Copy is negligible, copying a large memory block will always saturate the CPU (ie. 100% usage of one core). There is nothing you can do except eliminating the copy operation completely (which may or may not be possible, depending on how you use the buffers).
If you are in the second case and the arrays are very small it may be worth switching to a purely managed loop. But don't do this without measuring, it's easy to guess wrong, and the unmanaged implementation of Marshal.Copy can pull more tricks than the managed JIT to make up for the overhead.
PS: You might want to read this - high CPU usage by itself is no bad thing, the computer is just trying to get things done as fast as possible. Managed or unmanaged does not matter, if your usage is below 100% (per core) it just means your computer got nothing to do.
Can there be buffer overflow/overrun vulnerabilities in completely managed asp.net web portal.If yes how can this be tested.
In the general case, you don't need to worry about buffer overruns. This is one of the major advantages of managed code, garbage collection being perhaps the other major advantage.
There are a few edge cases that you should be aware of - any time your managed code interacts with unmanaged code (Win32 API calls, COM interop, P/Invoke, etc) there is a potential for buffer overruns in the unmanaged code, based on parameters passed in from managed code.
Also code marked as "unsafe" can directly manipulate memory addresses in such a way as to cause buffer overflow. Most C# code is written without using the "unsafe" keyword, though.
Not unless you exploit the webserver or .NET/ASP.NET stack itself.
I had a tool (HP Dev Inspect) detect a possible "Possible Parameter Buffer Overflow" within my ASP.NET app and it was because we didn't have a MaxLength="20" in one of our TextBoxes...