Dotnet не вызывает свой финализатор, даже если объект выходит из области видимости.Как освободить неуправляемые ресурсы? - PullRequest
0 голосов
/ 12 сентября 2018

Я попытался с помощью следующего кода

[DllImport("Core.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateNode();

[DllImport("Core.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void ReleaseNode(IntPtr handle);

 class Node
{
    IntPtr nativePtr;
    public int id;
    public Node(int i)
    {
        nativePtr = CreateNode();
        id = i;
        Debug.WriteLine("Constructed " + id);
    }

    ~Node()
    {
        ReleaseNode(nativePtr);
        Debug.WriteLine("Destructed " + id);
    }
}

    class Program
    {
        static void Main(string[] args)
        {

            for (int i = 0; i < 10; i++)
            {
                Node n = new Node(i);
            } //this scope
        }
    }

Каждый объект для класса Node, созданный внутри цикла for, не разрушается после выхода из области действия цикла for (прокомментируется как "this scope").он вызывается только тогда, когда заканчивается область действия метода Main.Можно ли автоматически вызывать узел ~, когда заканчивается область цикла for?

при выполнении кода выше, в окне отладки я получаю следующее:

Constructed 0
Constructed 1
Constructed 2
Constructed 3
Constructed 4
Constructed 5
Constructed 6
Constructed 7
Constructed 8
Constructed 9
Destructed 9
Destructed 0
Destructed 8
Destructed 7
Destructed 6
Destructed 5
Destructed 4
Destructed 3
Destructed 2
Destructed 1

это показывает, чтопервый объект разрушается в конце концов.Если это произойдет, что произойдет, когда я запускаю тысячи элементов в цикле?Будет ли это занимать всю мою память?

Как я могу полностью освободить свои неуправляемые ресурсы?

Ответы [ 3 ]

0 голосов
/ 12 сентября 2018

C # (и .Net Framework в целом) использует Сборщик мусора для управления памятью, поэтому вам не нужно об этом беспокоиться. Если вы работаете с c ++, поначалу это может показаться немного странным, но GC хорошо справляется со своей задачей. Финализаторы вызываются сборщиком мусора, и документы прямо говорят:

Программист не может контролировать, когда вызывается финализатор. потому что это определяется сборщиком мусора.

Если у вас большой класс ресурсов, и вы хотите контролировать, когда ресурсы будут освобождены, вы должны использовать операторы IDisposable и using.

0 голосов
/ 12 сентября 2018

Вызов финализатора осуществляется сборщиком мусора.Чтобы иметь полный контроль над неуправляемыми ресурсами, используйте одноразовый шаблон

class MyResource : IDisposable
{
  ~MyResource()
  {
    Dispose(false);
  }

  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this); // don't finalize after the object has already been disposed of
  }

  protected void Dispose(bool disposing)
  {
    if(disposing)
    {
      // TODO: Dispose managed resources
    }

    // TODO: Dispose unmanaged resources
  }
}

// when using
using(var resource = new MyResource())
{
  // ... use resource
} // when out of "using" scope, it will be disposed
0 голосов
/ 12 сентября 2018

TL; DR: Избавьтесь от финализатора, если это возможно, и просто доверьтесь сборщику мусора, чтобы он поступил правильно.

Завершение не является детерминированным. Важно понимать, что объекты не выходят за рамки; у объекта нет области видимости для начала. Переменные выходят из области видимости, и это ничего не вызывает.

Обычно сборщик мусора запускается только тогда, когда это необходимо. Нет гарантии относительно порядка, в котором будут вызываться финализаторы, или когда они будут вызваны. (Хотя вы можете запросить запуск сборщика мусора, это, как правило, плохая идея, и в любом случае у нее мало гарантий.)

Почти всегда плохая идея иметь финализатор в ваших собственных классах, хотя: он задерживает фактическую сборку мусора, и почти всегда есть лучшие подходы к тому, что вы будете делать в финализаторе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...