我正在开发一个OpenCV项目,我必须使用Mat * s(我不知道为什么不仅仅是Mat对象!!!)。无论如何,我在内存管理方面遇到了困难。
Mat* m = new Mat ( *MatPointerReturningFunc(..))
or
Mat* m = new Mat ( MatPointerReturningFunc(..)->clone())
当我在visual studio调试模式中执行这些步骤时,我可以看到任务管理器上增加的内存。无论我做了什么,我都无法释放这些矩阵。
m-> release()//不会工作,因为m没有自己的内存空间
*(m-> refcount)= 0 //也没有任何效果。
删除m //未观察到任何效果
我真的被卡住了,我不知道如何修复,相关的内存泄漏问题。
提前感谢您的帮助。
答案 0 :(得分:0)
绝对可以使用cv :: Mat指针,但是(和所有指针一样)你必须特别注意删除创建的对象,以便再次释放已分配的内存。
在您的示例代码中,不清楚在函数中返回其指针的对象是否会被删除。如果不是这种情况,cv :: Mat像素数据的引用计数将无法按预期工作,此外,一些(次要)内存将被cv :: Mat对象本身泄露。如此简短:对于每个new cv::Mat
,必须有delete
,因此如果外部函数中有new
,则可能需要为其调用delete
(如果该函数不会通过稍后的某些智能类功能来实现。更具体的是,Mat* m = new Mat ( *MatPointerReturningFunc(..))
将创建一个新的cv :: Mat对象,因为你可以在以后删除它,但是函数返回的指针会丢失。如果要创建新的Mat对象(或者只使用returnedPtr而不创建新对象),请尝试cv::Mat * returnedPtr = MatPointerReturningFunc(..);
后跟cv::Mat * m = new cv::Mat(*returnedPtr);
。
以下是一些示例代码,其中包含2个不同的Mat Ptr返回函数以及在有或没有泄漏的情况下访问它们的一些方法。
重要提一下," best"使用指针的方式通常是智能指针,由OpenCV明确给出。但更好的是不要将指针用于cv :: Mat对象,因为它不易出错,并且没有太多开销。引用计数非常好,您通常不会使用int
或std::vector
或std::string
等指针作为指针;)
cv::Mat* MatPointerReturningFunc()
{
// this function allocates new memory by first creating a new cv::Mat object on heap (just some bytes for the Mat header)
// and second by allocating new reference counted data in that cv::Mat object (pixel memory = 640*480*3 bytes)
cv::Mat * functionMat = new cv::Mat(480, 640, CV_8UC3, cv::Scalar(rand()%255, rand()%255, rand()%255));
return functionMat;
}
cv::Mat* MatPointerReturningFunc2(cv::Mat * input)
{
// this function does not allocate new memory on the heap, just modifies the input data
cv::circle(*input, cv::Point(320, 240), 100, cv::Scalar(rand() % 255, rand() % 255, rand() % 255), -1);
return input;
}
int main(int argc, char* argv[])
{
while (cv::waitKey(0) != 'q')
{
cv::Mat * mainMat;
cv::Mat * anotherMat;
// this will not leak, because the memory which was allocated in the function, is destroyed afterwards
// and the reference counter of the openCV Mat pixel-data is decremented
if (true)
{
mainMat = MatPointerReturningFunc();
cv::imshow("main", *mainMat);
delete mainMat;
}
// this will leak because the returned Mat object will not be deleted, only the here created one - that's why the reference counting is stuck at one referenced object
if (false)
{
mainMat = new cv::Mat(*MatPointerReturningFunc());
delete mainMat;
}
// this will not leak, since all references to the Mat data are destroyed (the returned Mat and the locally created new Mat)
if (true)
{
mainMat = MatPointerReturningFunc();
cv::Mat * anotherMat = new cv::Mat(*mainMat);
cv::imshow("main", *mainMat);
cv::imshow("another", *anotherMat);
cv::imshow("another", *anotherMat);
delete mainMat;
delete anotherMat;
}
// this will not leak because all references are destroyed
if (true)
{
mainMat = MatPointerReturningFunc();
cv::imshow("main", *mainMat);
anotherMat = new cv::Mat(mainMat->clone());
cv::imshow("another", *anotherMat);
delete mainMat;
delete anotherMat;
}
// now here we work with the second function which does not allocate new memory but only modifies the input matrix
if (true)
{
// first we have to allocate memory, otherwise the input mat can't be modified ;)
mainMat = new cv::Mat(480, 640, CV_8UC3, cv::Scalar(255, 255, 255));
cv::imshow("main", *mainMat);
// this does not leak because the second functions doesn't allocate new memory:
// however we have to delete mainMat later, because we created it before.
if (true)
{
anotherMat = MatPointerReturningFunc2(mainMat);
cv::imshow("another", *anotherMat);
}
// this does not leak because we delete the new created Mat object here and the before created mainMat later
if (true)
{
anotherMat = new cv::Mat(*MatPointerReturningFunc2(mainMat));
cv::imshow("another", *anotherMat);
delete anotherMat;
}
// this does not leak because we delete the new created Mat object here and the before created mainMat later
// in fact, this way will allocate new pixel data because of the clone(), but we will free the memory with `delete anotherMat`directly
if (true)
{
anotherMat = new cv::Mat(MatPointerReturningFunc2(mainMat)->clone());
cv::imshow("another", *anotherMat);
delete anotherMat;
}
// since we created the object and allocated memory, we have to give it free here again
delete mainMat;
}
// in fact, if you WANT to use Pointers with OpenCV Mat objects you should use smart pointers.
// OpenCV has its own smart pointers, but I guess you could use any other smart pointers
// create a Mat object on the heap, allocate pixel data and access all this by a smart pointer!
cv::Ptr<cv::Mat> smartPtr = new cv::Mat(480, 640, CV_8UC3, cv::Scalar(rand()%255, rand()%255, rand()%255) );
cv::imshow("smart pointer", *smartPtr);
// no need to delete the created Mat on the smart pointer, because the smart pointer has its own reference counting
}
return 0;
}