首页 > 解决方案 > 垫子没有被正确销毁

问题描述

在我用 C# 编写的软件中,我实现了一个用于内部目的的图像类。在那个班级里,我拿着一份Mat来自 emgu 的简历。

class MyOwnImage : IDisposable
{
    private Mat mat;

    public MyOwnImage( Mat mat ) {
        this.mat = mat;
    }

    public void Dispose() {
        mat.Dispose();
    }
    //...
}

Dispose()现在,我发现,无论我是否调用Image对象,我的内存使用量都在增长。我仔细看了看这Mat门课,发现它里面有一个IntPtr. 所以,我试了一下,如果手动释放指针会有所不同:

class MyOwnImage : IDisposable
{
    private Mat mat;

    public MyOwnImage( Mat mat ) {
        this.mat = mat;
    }

    public void Dispose() {
        Marshal.FreeHGlobal( mat.DataPointer ); // data pointer is the IntPtr
        mat.Dispose();
    }
    //...
}

我有点惊讶,但它解决了内存溢出的问题。所以,我假设我必须Mat手动销毁对象内部的数据。Dispose()之后,如果有人忘记手动生成图像,我尝试通过添加析构函数来使其更加稳定。

class MyOwnImage : IDisposable
{
    private Mat mat;

    public MyOwnImage( Mat mat ) {
        this.mat = mat;
    }

    ~MyOwnImage() {
        destroy();
    }

    private void destroy() {
        Marshal.FreeHGlobal( mat.DataPointer ); // data pointer is the IntPtr
        mat.Dispose();
    }

    public void Dispose() {
        destroy();
    }
    //...
}

可悲的是,这变成了一个新问题:有时,当调用析构函数时,Mat对象似乎已经被销毁了。随后,AccessViolationExcetion在调用FreeHGlobal(...). 现在,我进行了另一个测试并删除destroy()了函数内部的Dispose()调用。

class MyOwnImage : IDisposable
{
    private Mat mat;

    public MyOwnImage( Mat mat ) {
        this.mat = mat;
    }

    ~MyOwnImage() {
        destroy();
    }

    private void destroy() {
        Marshal.FreeHGlobal( mat.DataPointer ); // data pointer is the IntPtr
        mat.Dispose();
    }

    public void Dispose() {
        //destroy();
    }
    //...
}

奇怪的是,这并没有改变任何事实,当调用析构函数时,mat内部MyOwnImage似乎已经消失了~MyOwnImage

最后,我想知道几件事:

  1. 如果我手动调用Dispose(),是否有可能稍后也会调用析构函数?
  2. 有没有可能在MyOwnImage这个类的析构函数被调用之前,内部对象就被销毁了?
  3. 如果有 OpenCV 专家:是否有可能处理垫子不会释放里面的数据?如果是,是错误还是有原因?

标签: c#emgucv

解决方案


J...在评论中指出了这个问题。

违反了所有权模式。正如他所建议的,我Mat在 MyOwnImage 中克隆了该对象,现在它正在工作。

class MyOwnImage : IDisposable
{
    private Mat mat;

    public MyOwnImage( Mat passedMat ) {
        var copy = new Mat();
        passedMat.CopyTo( copy );
        mat = copy;
    }

    public void Dispose() {
        mat.Dispose();
    }
    //...
}

推荐阅读