为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
函数式编程 2022-09-04 16:23:27
我有一个类,它通过分配一个内存块。该类实现,我已将其设置为在类最终确定时自动释放分配的内存。但是,它似乎未按预期工作。MappedMemoryMarshal.AllocHGlobal()IDisposableclass 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()我对这里发生的事情感到非常困惑。有人可以解释为什么终结器不能释放内存,以及我如何确保它在生产中释放内存吗?
查看完整描述

1 回答

?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

从 MSDN 文档中,此处为:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/destructors

程序员无法控制何时调用终结器,因为这是由垃圾回收器确定的。垃圾回收器检查应用程序不再使用的对象。如果它认为某个对象符合完成条件,它将调用终结器(如果有)并回收用于存储该对象的内存。

正如您所说,强制垃圾回收会释放内存,我怀疑您看到的问题是内存系统上没有足够的压力来导致垃圾回收自动运行。垃圾回收是一个相对昂贵的过程,因此除非有理由这样做,否则它不会运行。


查看完整回答
反对 回复 2022-09-04
  • 1 回答
  • 0 关注
  • 145 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号