Writing memleak-free code in C++ isn't a problem for me, I just keep to the RAII idiom.
Writing memleak-free code in C# isn't very hard either, the garbage collector will handle it.
Unfortunately, writing C++/CLI code is a problem for me. I thought I had understood how it works, but I still have big problems and I hope you can give me some hints.
This is what I have:
A Windows service written in C# that uses C++ libraries (for example OpenCV) internally. The C++ classes are accessed with C++/CLI wrapper classes.
For example I have a MatW
C++/CLI wrapper class for a cv::Mat
image object, which takes as constructor argument a System::Drawing::Bitmap
:
public ref class MatW
{
public:
MatW(System::Drawing::Bitmap ^bmpimg)
{
cv::Size imgsize(bmpimg->Width, bmpimg->Height);
nativeMat = new Mat(imgsize, CV_8UC3);
// code to copy data from Bitmap to Mat
// ...
}
~MatW()
{
delete nativeMat;
}
cv::Mat* ptr() { return nativeMat; }
private:
cv::Mat *nativeMat;
};
Another C++ class might be for example
class PeopleDetector
{
public:
void detect(const cv::Mat &img, std::vector<std::string> &people);
}
And its wrapper class:
public ref class PeopleDetectorW
{
public:
PeopleDetectorW() { nativePeopleDetector = new PeopleDetector(); }
~PeopleDetectorW() { delete nativePeopleDetector; }
System::Collections::Generic::List<System::String^>^ detect(MatW^ img)
{
std::vector<std::string> people;
nativePeopleDetector->detect(*img->ptr(), people);
System::Collections::Generic::List<System::String^>^ peopleList = gcnew System::Collections::Generic::List<System::String^>();
for (std::vector<std::string>::iterator it = people.begin(); it != people.end(); ++it)
{
System::String^ p = gcnew System::String(it->c_str());
peopleList->Add(p);
}
return peopleList;
}
And here is the call to the method in my Windows Service C# class:
Bitmap bmpimg = ...
using (MatW img = new MatW(bmpimg))
{
using (PeopleDetectorW peopleDetector = new PeopleDetector())
{
List<string> people = peopleDetector.detect(img);
}
}
Now, here's my questions:
- is there anything wrong with my code?
- do I have to use
using
in my C# code? It makes the code ugly, when there are multiple wrapper objects in use, because theusing
statements have to be nested - could I use
Dispose()
instead after having used the objects? - Could I just not bother and leave it to the garbage collector?
(no
using
, noDispose()
) - is the above code the right way to return objects like
List<string^>^
from C++/CLI to C#? - does using
gcnew
not mean that the garbage collector will take care of the objects and I don't have to care how and when to free them?
I know that's a lot of questions, but all I want is to get rid of my memory leak, so I listed everything that I think could possibly go wrong...