I have a C++ dll which is reading video frames from a camera. These frames get allocated in the DLL returned via pointer to the caller (a C# program).
When C# is done with a particular frame of video, it needs to clean it up. The DLL interface and memory management is wrapped in a disposable class in C# so its easier to control things. However, it seems like the memory doesn't get freed/released. The memory footprint of my process grows and grows and in less than a minute, I get allocation errors in the C++ DLL as there isn't any memory left.
The video frames are a bit over 9 MB each. There is a lot of code, so I'll simply provide the allocation/deallocations/types/etc.
First : Allocation in C++ of raw buffer for the camera bytes.
dst = new unsigned char[mFrameLengthInBytes];
Second : transfer from the raw pointer back to across the DLL boundary as an unsigned char * and into an IntPtr in C#
IntPtr pFrame = VideoSource_GetFrame(mCamera, ImageFormat.BAYER);
return new VideoFrame(pFrame, .... );
So now the IntPtr is passed into the CTOR of the VideoFrame class. Inside the CTOR the IntPtr is copied to an internal member of the class as follows :
IntPtr dataPtr;
public VideoFrame(IntPtr pDataToCopy, ...)
{
...
this.dataPtr = pDataToCopy;
}
My understanding is that is a shallow copy and the class now references the original data buffer. The frame is used/processed/etc. Later, the VideoFrame class is disposed and the following is used to clean up the memory.
Marshal.FreeHGlobal(this.dataPtr);
I suspect the problem is that... dataPtr is an IntPtr and C# has no way to know that the underlying buffer is actually 9 MB, right? Is there a way to tell it how much memory to release at that point? Am I using the wrong C# free method? Is there one specifically for this sort of situation?
You need to call the corresponding "free" method in the library you're using.
Memory allocated via new is part of the C++ runtime, and calling FreeHGlobal won't work. You need to call (one way or the other) delete[] against the memory.
If this is your own library then create a function (eg VideoSource_FreeFrame) that deletes the memory. Eg:
void VideoSource_FreeFrame(unsigned char *buffer)
{
delete[] buffer;
}
And then call this from C#, passing in the IntPtr you got back.
You need to (in c++) delete dst;. That means you need to provide an API that the C# code can call, like FreeFrame(...), which does exactly that.
I agree with the first answer. Do NOT free it in C# code, using any magical, liturgical incantations. Write a method in C++ that free's the memory, and call it from your C# code. Do NOT get into the habit of allocationg memory in one heap (native) and freeing it another heap (managed), that's just bad news.
Remember one of the rules from the book effective C++: Allocate memory in the constructor, and deallocate in the destructor. And if you can't do it in the destructor, do it in an in-class method, not some global (or even worse) friend function.
Related
I have a C# program that calls a C++ DLL. The wrapper code for the function is question is shown below.
As this function is called repeatedly, memory use continues to grow and it appears as if there's a memory leak. And it appears that the issue is associated with the matchingFragments->Add line in the code below. If I comment out that line, memory use is stable.
In previous iterations of this program, where matchingFragments wasn't a list but was set to a fixed number of elements, memory use would be stable throughout repeated calls to this function. So I suspect some memory isn't being freed somewhere, but I don't know what the issue is, whether it's matchedFragments, returnedFragments, or neither. Nor do I know any of this well enough (I'm a C developer struggling with this) to know how to debug this, so any suggestions would be appreciated.
bool SearchWrapper::SpectrumSearch([Out] List<FragmentWrapper^>^% returnedFragments)
{
vector<Fragment> matchedFragments;
// perform the search
bool isSuccess = _pSearchMgr->PeptideSearch(matchedFragments);
// Convert data back to the managed world
returnedFragments = gcnew List<FragmentWrapper^>();
for (auto frag : matchedFragments)
{
returnedFragments->Add(gcnew FragmentWrapper(frag));
}
return isSuccess;
}
Turns out the actual fix to my issue was the need for a finalizer for the FragmentWrapper class. There was a destructor but not a finalizer. Once I added the finalizer, the memory leak went away.
Say I have a structure with several members eg.
private struct MyStats
{
public int packsGood, packsBad, packsTotal;
public bool haveAcceptedStart;
// ...and a bunch of other parameters
}
If I have a member variable of type MyStats, how do I use it for a while and then quickly clear it? In Delphi or C++ I might have used the following code:
memset(&m_stats, 0, sizeof(MyStats)); // C++
ZeroMemory(#m_stats, SizeOf(MyStats)); // Delphi
but that doesn't appear possible in C#. Surely I don't have to rattle through all members each time or PInvoke an API call?
Memory Management should generally not be one of your concerns in C#, as opposed to C or C++. There is the garbage collector to take care of memory clearing. As soon as all the references to your struct have disappeared, the garbage collector will reclaim the memory somewhere in the future. When exactly is irrelevant for a developer.
If you have a field in your class just to be used for a while an clearing it then your class isn't properly designed and does not comply with OOP principles.
If you are using that field just as an auxiliary value you should just replace it with a variable in every scope it is used; in this way you'll reduce the number of daunting side effects and since it's a value type it will be allocated on the stack and cleared as soon as the control flow leaves the current block (given you don't capture it in a lambda expression).
I have written some code to retrieve frames from a camera, along with information obtained from these frames, and to display them on a form.
All the data that I get is unmanaged as it comes form a library of my own written in c++ and working with OpenCv.
I prefer getting all the data at once with a single function call and not using a wrapper to OpenCv that would PInvoke several times to get the same result. Furthermore for me the code is easier to maintain and I have much more control on everything that is going on and I have many other reason to prefer this approach.
Everything is ok, (seemingly) perfectly working and I’m happy, but… there is something I would like to understand better with your help.
At a certain point I create a bitmap with the unmanaged pixel data with the method
public Bitmap(int width,int height,int stride,PixelFormat format, IntPtr scan0);
My question are the following (I have some idea, but just tell me if I’m right) :
1) I don’t release the data pointed by scan0 as I think that, once the data is owned by the bitmap object, it will do the job for me via its Garbage Collection. Am I right?
2) I don’t like the fact that a new instance of bitmap is created and allocated every time (apart from the pixel data), but I suppose that there is no better way of getting a Bitmap out of unmanaged data.
3) I think that there is no need to tell the Garbage Collector that there is a big amount of data to clean up with GC.AddMemoryPressure(…) as it knows it, estimating from the information provided with the initialization.
EDIT
I've found on the documentation
The caller is responsible for allocating and freeing the block of memory specified by the scan0 parameter. However, the memory should not be released until the related Bitmap is released.
The only way to do this is that the Bitmap object created in such a way leaves the data untouched and doesn't change its position in memory.
1) I don’t release the data pointed by scan0 as I think that, once the
data is owned by the bitmap object, it will do the job for me via its
Garbage Collection. Am I right?
No, the garbage collector knows nothing about the object, which you've initialized on the unmanaged side, that is why it is unmanaged. So you have to call delete in the unmanaged code to release the allocated memory.
2) I don’t like the fact that a new instance of bitmap is created and
allocated every time (apart from the pixel data), but I suppose that
there is no better way of getting a Bitmap out of unmanaged data.
There is a way and a keyword is unsafe. You can run the c++ code inside of the unsafe block, but you must allow this in the c# project settings. So you can reuse every pixel of once initialized bitmap
unsafe
{
byte stlThres = 115;
Bitmap myBmp = ...; // init the bitmap
var data = myBmp.LockBits(new Rectangle(0, 0, myBmp.Width, myBmp.Height), ImageLockMode.WriteOnly, myBmp.PixelFormat);
for (int y = 0; y < data.Height; y++)
{
byte* row = (byte*)data.Scan0 + (y * data.Stride);
//...
}
3) I think that there is no need to tell the Garbage Collector that
there is a big amount of data to clean up with GC.AddMemoryPressure(…)
as it knows it, estimating from the information provided with the
initialization.
If you created a managed Bitmap object (with new), it will be released automatically after it gets out of scope or will not be referenced any longer.
I call a piece of an unmanaged C++ code from my C# application
to calculate fast fourier transform of a discrete time signal.
I make a call something like this
IntPtr ptr = ComputeFFTW(packetSig, packetSig.Length, (int)samplFrequency,(int)fftPoints);
unsafe
{
double *dPtr = (double*)ptr;
for(int l = 0; l < fftData.Length; l++)
{
fftData[l] = dPtr[l];
}
}
Though this snippet of code works fine and gives me the desired results, i can see that there is sort of performance hit (memory leak) is incurred while calculation is in progress. The CLR fails to reclaim the local (double) variables and my application gobbles up RAM space considerably.
Can anyone of you suggest the places where i might be doing it wrong.
From my side, I ran my application using ANTS Mem Profiler and i can see on the snapshot that the double objects nearly claim >150MB of the mem space. Is this a normal behaviour ??
Class Name Live Size (bytes) Live Instances
Double[] 150,994,980 3
Any help is appreciated in this regard
Srivatsa
Since the C++ function allocates memory you will have to manually free that chunk in your C# application (free the pointer). A better way to do invoke unmanaged code is to allocate all the variables and memory chunks (Temp parameters too) in your C# application and pass them to your C++ code as parameters. In this way you wont have any memory issues with your unmanaged code.
You can use Marshal.Copy(IntPtr, Double[], Int32, Int32) method to copy array of double values from unmanaged ptr to managed ffData array:
IntPtr ptr = ComputeFFTW(packetSig, packetSig.Length, (int)samplFrequency,(int)fftPoints);
Marshal.Copy(ptr, fftData, 0, fftData.Length);
If ComputeFFTW returns pointer to dynamically allocated memory, you need to release it after using. Make this in unmanaged code, add function like Release and pass ptr to it.
I'm trying to use an unmanaged C dll for loading image data into a C# application. The library has a fairly simple interface where you pass in a struct that contains three callbacks, one to receive the size of the image, one that receives each row of the pixels and finally one called when the load is completed. Like this (C# managed definition):
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct st_ImageProtocol
{
public st_ImageProtocol_done Done;
public st_ImageProtocol_setSize SetSize;
public st_ImageProtocol_sendLine SendLine;
}
The types starting st_ImageProtocol are delgates:
public delegate int st_ImageProtocol_sendLine(System.IntPtr localData, int rowNumber, System.IntPtr pixelData);
With the test file that I'm using the SetSize should get called once, then the SendLine will get called 200 times (once for each row of pixels in the image), finally the Done callback gets triggered. What actually happens is that the SendLine is called 19 times and then a AccessViolationException is thrown claiming that the library tried to access protected memory.
I have access to the code of the C library (though I can't change the functionality) and during the loop where it calls the SendLine method it does not allocate or free any new memory, so my assumption is that the delegate itself is the issue and I need to pin it before I pass it in (I have no code inside the delegate itself currently, besides a counter to see how often it gets called, so I doubt I'm breaking anything on the managed side). The problem is that I don't know how to do this; the method I've been using to declare the structs in unmanaged space doesn't work with delegates (Marshal.AllocHGlobal()) and I can't find any other suitable method. The delegates themselves are static fields in the Program class so they shouldn't be being garbage collected, but I guess the runtime could be moving them.
This blog entry by Chris Brumme says that delegates don't need to be pinned before being passed into unmanaged code:
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.
But I don't know if this holds true when the delegate is part of a struct. It does imply that it is possible to manually pin them though, and I'm interested in how to do this or any better suggestions as to why a loop would run 19 times then suddenly fail.
Thanks.
Edited to answer Johan's questions...
The code that allocates the struct is as follows:
_sendLineFunc = new st_ImageProtocol_sendLine(protocolSendLineStub);
_imageProtocol = new st_ImageProtocol()
{
//Set some other properties...
SendLine = _sendLineFunc
};
int protocolSize = Marshal.SizeOf(_imageProtocol);
_imageProtocolPtr = Marshal.AllocHGlobal(protocolSize);
Marshal.StructureToPtr(_imageProtocol, _imageProtocolPtr, true);
Where the _sendLineFunc and the _imageProtocol variables are both static fields of the Program class. If I understand the internals of this correctly, that means that I'm passing an unmanaged pointer to a copy of the _imageProtocol variable into the C library, but that copy contains a reference to the static _sendLineFunc. This should mean that the copy isn't touched by the GC - since it is unmanaged - and the delegate won't be collected since it is still in scope (static).
The struct actually gets passed to the library as a return value from another callback, but as a pointer:
private static IntPtr beginCallback(IntPtr localData, en_ImageType imageType)
{
return _imageProtocolPtr;
}
Basically there is another struct type that holds the image filename and the function pointer to this callback, the library figures out what type of image is stored in the file and uses this callback to request the correct protocol struct for the given type. My filename struct is declared and managed in the same way as the protocol one above, so probably contains the same mistakes, but since this delegate is only called once and called quickly I haven't had any problems with it yet.
Edited to update
Thanks to everybody for their responses, but after spending another couple of days on the problem and making no progress I decided to shelve it. In case anyone is interested I was attempting write a tool for users of the Lightwave 3D rendering application and a nice feature would have been the ability to view all the different image formats that Lightwave supports (some of which are fairly exotic). I thought that the best way to do this would be to write a C# wrapper for the plugin architecture that Lightwave uses for image manipulation so I could use their code to actually load the files. Unfortunately after trying a number of the plugins against my solution I had a variety of errors that I couldn't understand or fix and my guess is that Lightwave doesn't call the methods on the plugins in a standard way, probably to improve the security of running external code (wild stab in the dark, I admit). For the time being I'm going to drop the image feature and if I do decide to reinstate it I'll approach it in a different way.
Thanks again, I learnt a lot through this process even though I didn't get the result I wanted.
I had a similar problem when registering a callback delegate (it would be called, then poof!). My problem was that the object with the method being delegated was getting GC'ed. I created the object in a more global place so as to keep it from being GC'ed.
If something like that doesn't work, here are some other things to look at:
As additional info, take a look at GetFunctionPointerForDelegate from the Marshal class. That is another way you could do this. Just make sure that the delegates are not GC'ed. Then, instead of delegates in your struct, declare them as IntPtr.
That may not solve the pinning, but take a look at fixed keyword, even though that may not work for you since you are dealing with a longer lifetime than for what that is typically used.
Finally, look at stackalloc for creating non-GC memory. These methods will require the use of unsafe, and might therefore put some other constraints on your Assemblies.
It would be interesting to know a little more:
How do you create the ImageProtocol struct? Is it a local variable or a class member or do you allocate it in unmanaged memory with Marshal.AllocHGlobal?
How is it sent to the C function? Directly as stack variable or as a pointer?
A really tricky problem! It feels like the delegate data is moved around by the GC which causes the access violation. The interesting thing is that the delegate data type is a reference data type, which stores its data on the GC heap. This data contains things like the address of the function to call (function pointer) but also a reference to the object that contains the function. This should mean that even though the actual function code is stored outside of the GC heap, the data that holds the function pointer is stored in the GC heap and can hence be moved by the GC. I thought about the problem a lot last night but haven't come up with a solution....
You don't say exactly how the callback is declared in the C library. Unless it is explictly declared __stdcall you'll slowly corrupt your stack. You'll see your method get called (probably with the parameters reversed) but at some point in the future the program will crash.
So far as I know there is no way around that, other than writing another callback function in C that sits between the C# code and the library that wants a __cdecl callback.
If the c function is a __cdecl function then you have to use the Attribut
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
before the delegate declaration.