用 C++ 编写无 memleak 代码对我来说不是问题,我只是坚持使用RAII习语。
用 C# 编写无 memleak 代码也不是很难,垃圾收集器会处理它。
不幸的是,编写 C++/CLI 代码对我来说是个问题。我以为我已经理解了它的工作原理,但是我仍然有很大的问题,希望您能给我一些提示。
这就是我所拥有的:
用 C# 编写的 Windows 服务,它在内部使用 C++ 库(例如 OpenCV)。C++ 类通过 C++/CLI 包装类访问。例如,我有一个MatW
用于图像对象的 C++/CLI 包装类cv::Mat
,它将 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;
};
例如,另一个 C++ 类可能是
class PeopleDetector
{
public:
void detect(const cv::Mat &img, std::vector<std::string> &people);
}
及其包装类:
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;
}
这是对我的 Windows 服务 C# 类中的方法的调用:
Bitmap bmpimg = ...
using (MatW img = new MatW(bmpimg))
{
using (PeopleDetectorW peopleDetector = new PeopleDetector())
{
List<string> people = peopleDetector.detect(img);
}
}
现在,这是我的问题:
- 我的代码有什么问题吗?
- 我必须
using
在我的 C# 代码中使用吗?当使用多个包装器对象时,它会使代码变得丑陋,因为using
必须嵌套语句 - 我可以
Dispose()
在使用这些对象后改用吗? - 我可以不打扰并将其留给垃圾收集器吗?(不
using
,不Dispose()
) - 上面的代码是将对象
List<string^>^
从 C++/CLI 返回到 C# 的正确方法吗? - using
gcnew
并不意味着垃圾收集器会处理这些对象,而我不必关心如何以及何时释放它们?
我知道这是很多问题,但我只想摆脱我的内存泄漏,所以我列出了我认为可能出错的所有内容......