C# 终结器未释放非托管内存

我有一个类,它通过分配一个内存块。该类实现,我已将其设置为在类最终确定时自动释放分配的内存。但是,它似乎未按预期工作。MappedMemoryMarshal.AllocHGlobal()IDisposable


class MappedMemory : IDisposable

{

    private bool disposed_ = false;

    private IntPtr memoryPtr_;


    public MappedMemory( int capacity )

    {

      memoryPtr_ = Marshal.AllocHGlobal( capacity );

    }


    ~MappedMemory()

    {

      Dispose( false );

    }


    public void Dispose()

    {

      Dispose( true );

      GC.SuppressFinalize( this );

    }


    protected virtual void Dispose( bool disposing )

    {

      if ( !disposed_ )

      {

        if ( disposing )

        {

          // Clear managed resources

        }


        Marshal.FreeHGlobal( memoryPtr_ );

      }

      disposed_ = true;

    }

}

我已经编写了两个测试来确保内存被正确释放:


public MappedMemory_finalizer_frees_memory()

{

  for( var i = 0; i < 1e8; i++ )

  {

    var memory = new MappedMemory( 128 );

  }

}


public MappedMemory_dispose_frees_memory()

{

  for( var i = 0; i < 1e8; i++ )

  {

    var memory = new MappedMemory( 128 );

    memory.Dispose();

  }

}

运行测试时,手动调用的测试将按预期工作,并且内存保持恒定利用率。Dispose()


但是,终结器的测试似乎没有释放分配的内存,并且在内存耗尽之前会失控泄漏。我设置了一个断点,并且命中了对的调用。Marshal.FreeHGlobal( memoryPtr_ )


手动添加到测试中可以解决问题,因此最终看起来内存已解除分配,但未被垃圾回收?GC.Collect()


我对这里发生的事情感到非常困惑。有人可以解释为什么终结器不能释放内存,以及我如何确保它在生产中释放内存吗?


函数式编程
浏览 146回答 1
1回答

白猪掌柜的

从 MSDN 文档中,此处为:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/destructors程序员无法控制何时调用终结器,因为这是由垃圾回收器确定的。垃圾回收器检查应用程序不再使用的对象。如果它认为某个对象符合完成条件,它将调用终结器(如果有)并回收用于存储该对象的内存。正如您所说,强制垃圾回收会释放内存,我怀疑您看到的问题是内存系统上没有足够的压力来导致垃圾回收自动运行。垃圾回收是一个相对昂贵的过程,因此除非有理由这样做,否则它不会运行。
打开App,查看更多内容
随时随地看视频慕课网APP