在我用C#编写的软件中,我实现了一个用于内部目的的映像类。在那节课上,我拿着emgu CV的Mat
。
class MyOwnImage : IDisposable
{
private Mat mat;
public MyOwnImage( Mat mat ) {
this.mat = mat;
}
public void Dispose() {
mat.Dispose();
}
//...
}
现在,我发现,无论我是否在Image
对象上调用Dispose()
,我的内存使用量都在不断增长。我仔细查看了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();
}
//...
}
不幸的是,这变成了一个新问题:当调用destructor时,Mat
对象似乎已经被破坏了。接下来,在调用FreeHGlobal(...)
的线路上抛出一个AccessViolationExcetion
。现在,我进行了另一个测试,并删除了Dispose()
函数中的destroy()
调用。
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();
}
//...
}
奇怪的是,这并没有改变这样一个事实,即当调用析构函数~MyOwnImage
时,MyOwnImage
中的mat
似乎已经不见了。
最后,我想知道几件事:
- 如果我手动调用
Dispose()
,那么以后也会调用析构函数吗 MyOwnImage
的内部对象是否可能在调用此类的析构函数之前被销毁- 如果有OpenCV专家:处理垫子是否可能无法释放里面的数据?如果是,这是一个错误还是有原因
J在评论中指出了这个问题。
违反了所有权模式。正如他所建议的,我在MyOwnImage中克隆了Mat
对象,现在它正在工作。
class MyOwnImage : IDisposable
{
private Mat mat;
public MyOwnImage( Mat passedMat ) {
var copy = new Mat();
passedMat.CopyTo( copy );
mat = copy;
}
public void Dispose() {
mat.Dispose();
}
//...
}