void hello(Mat original)
{
Mat a=original.clone();
Ptr<IplImage> b = &a.operator IplImage();
return;
}
此函数将导致内存异常。因为我必须使用参数为IplImage*的旧函数,所以我将Mat转换为Ptr并导致内存异常。上面的函数只是一个简化的版本。
From OpenCV doc
操作符为矩阵创建IplImage头,而不复制底层数据。当使用IplImage头文件时,你应该确保原始矩阵没有被释放
您可以将返回的头的引用传递给接受IplImage*
的函数,如下面代码中的void foo(IplImage* img)
:
#include <opencv2opencv.hpp>
using namespace cv;
void foo(IplImage* img)
{
// Set to blue
cvSet(img, Scalar(255,0,0));
}
int main()
{
// Small green image
Mat3b img(10, 10, Vec3b(0, 255, 0));
{
// Doesn't modify original image
Mat mat = img.clone();
IplImage ipl = mat;
foo(&ipl);
// ipl and mat are blue now
// img is still green
}
{
// Modify original image
IplImage ipl = img;
foo(&ipl);
// ipl and img are blue now
}
// img is blue
return 0;
}
Ptr<T>
是一个自动销毁包装对象指针的模板类(更多信息请参阅官方文档)。
在您的代码片段中,a
和b
都是函数hello
中的局部变量,因此它们将在该函数返回时被销毁,并且以相反的构造顺序,因此a
将在b
销毁之后被销毁。
内存异常可能发生,因为两个变量(a
和b
)引用相同的内存区域:事实上,函数Mat::operator IplImage
并不复制Mat
对象的底层数据,而是为这些矩阵数据创建IplImage
头。
因此,当Mat
析构函数试图销毁对象a
时,专用于底层数据的那部分内存已经被b
释放了。