在OpenCv中使用Ptr<IplImage>导致内存异常

Using Ptr<IplImage> in OpenCv causes memory exception

void hello(Mat original)
{
  Mat a=original.clone();
  Ptr<IplImage> b = &a.operator IplImage();
  return;
}

这个函数会导致内存异常。因为我必须使用一个参数为 IplImage* 的旧函数,所以我将 Mat 转换为 Ptr 并导致内存异常。以上功能只是一个简化版。

Ptr<T> 是一个模板 class,它执行包装的 object 指针的自动销毁(有关它的更多信息,请参阅 official documentation)。

在你的代码片段中,ab 都是函数 hello 内部的局部变量,所以它们会在这个函数 returns 和构造顺序相反,所以 a 将在 b.

销毁后被销毁

可能会出现内存异常,因为两个变量(ab)都引用了相同的内存区域:实际上,函数Mat::operator IplImage 并没有复制 Mat object 的基础数据 ,但为这些矩阵数据创建 IplImage header。

因此,当 Mat 析构函数将尝试销毁 object a 时,专用于基础数据的内存部分已经被 b 释放.

来自OpenCV doc

The operator creates the IplImage header for the matrix without copying the underlying data. You should make sure than the original matrix is not deallocated while the IplImage header is used.

您可以将返回的 header 的引用传递给接受 IplImage* 的函数,例如下面代码中的 void foo(IplImage* img):

#include <opencv2\opencv.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;
}