垫子没有被正确销毁
Mat is not being destroyed properly
在我用 C# 编写的软件中,我实现了一个图像 class 供内部使用。在 class 里面,我拿着来自 emgu CV 的 Mat
。
class MyOwnImage : IDisposable
{
private Mat mat;
public MyOwnImage( Mat mat ) {
this.mat = mat;
}
public void Dispose() {
mat.Dispose();
}
//...
}
现在,我发现,无论我是否在 Image
对象上调用 Dispose()
,我的内存使用量都在增长。我仔细查看了 Mat
class 并发现它内部有未管理的内存,形式为 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
对象似乎已经被销毁了。随后,在调用 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
的内部对象在调用此 class 的析构函数之前被销毁?
- 如果有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();
}
//...
}
在我用 C# 编写的软件中,我实现了一个图像 class 供内部使用。在 class 里面,我拿着来自 emgu CV 的 Mat
。
class MyOwnImage : IDisposable
{
private Mat mat;
public MyOwnImage( Mat mat ) {
this.mat = mat;
}
public void Dispose() {
mat.Dispose();
}
//...
}
现在,我发现,无论我是否在 Image
对象上调用 Dispose()
,我的内存使用量都在增长。我仔细查看了 Mat
class 并发现它内部有未管理的内存,形式为 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
对象似乎已经被销毁了。随后,在调用 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
的内部对象在调用此 class 的析构函数之前被销毁? - 如果有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();
}
//...
}