簡體   English   中英

C#終結器無法釋放非托管內存

[英]C# Finalizer not freeing unmanaged memory

我有一個MappedMemory類,它通過Marshal.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()的測試將按Dispose()工作,並且內存保持恆定的利用率。

但是,對終結器的測試似乎並未釋放分配的內存,並且它泄漏失控,直到內存用盡。 我設置了一個斷點,並調用了Marshal.FreeHGlobal( memoryPtr_ )

手動將GC.Collect()添加到測試中可解決此問題,因此最終看來似乎已釋放了內存,但未回收垃圾?

我對這里發生的事情感到非常困惑。 有人可以解釋一下終結器為什么不釋放內存,以及我如何確保在生產中使用它嗎?

從此處的MSDN文檔中: https : //docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/destructors

程序員無法控制何時調用終結器,因為這是由垃圾回收器確定的。 垃圾收集器檢查應用程序不再使用的對象。 如果認為某個對象適合終結,則調用終結器(如果有)並回收用於存儲該對象的內存。

正如您所說的那樣,強制垃圾回收會釋放內存,我懷疑您看到的問題是內存系統上的壓力不足,無法自動運行垃圾回收。 垃圾收集是一個相對昂貴的過程,因此除非有理由這樣做,否則它不會運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM