Нужно ли высвобождать память

Автор Тема: Нужно ли высвобождать память  (Прочитано 11622 раз)

0 Пользователей и 2 Гостей просматривают эту тему.

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Например, есть класс с полем
примитива AutoCAD Entity

Код - C# [Выбрать]
  1. public class MyClass {
  2.    public Entity Ent;
  3.    // Конструктор  
  4.    public MyClass(Entity ent) {
  5.            this.Ent = ent;  
  6.    }
  7. }

Начинаю работать с этим классом.
Код - C# [Выбрать]
  1. Line Ln = new Line(...);
  2. ...
  3. // obj - объявляется как глобальная переменная (чаще даже как массив объектов класса MyClass)
  4. MyClass obj = new MyClass((Entity)Ln.Clone());
  5. ...
  6. Ln =null;
  7.  
Когда объект obj уже больше не нужен.
если сделаю так:
Код - C# [Выбрать]
  1.  obj = null;
Что будет:
1) Останется мусор занятый ent (нужно будет вызвать ent.dispose())
2) Сборщик мусора сам высвободит память занятую ent

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Re: Нужно ли высвобождать память
« Ответ #1 : 13-09-2017, 15:01:03 »
Или нужно делать диспозе
в диструкторе класса MyClass

Код - C# [Выбрать]
  1. ~MyClass()  {
  2.      if (this.Ent != null)      
  3.           this.Ent.Dispose();
  4. }

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Нужно ли высвобождать память
« Ответ #2 : 13-09-2017, 15:10:02 »
В этом коде плохо абсолютно всё. И использование Entity как члена класса (да ещё и зачем-то public). И манера присвоения. Ты думаешь, что присвоение obj = null; освобождает память, которая была занята obj? Ты сильно заблуждаешься.
И вообще тебе как минимум в этой ситуации следует объявить в своём классе интерфейс IDisposable: https://msdn.microsoft.com/ru-ru/library/system.idisposable%28v=vs.110%29.aspx
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Re: Нужно ли высвобождать память
« Ответ #3 : 13-09-2017, 15:12:50 »
Ты думаешь, что присвоение obj = null; освобождает память
Вот вот я то и думаю что не высвободится памать-то и будет мусор.
 

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Re: Нужно ли высвобождать память
« Ответ #4 : 13-09-2017, 15:14:04 »
А что строка
Код - C# [Выбрать]
  1. obj=null;
разве не вызовет диструктор класса?

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Re: Нужно ли высвобождать память
« Ответ #5 : 13-09-2017, 15:17:00 »
да ещё и зачем-то public)
А на счет поля Ent, то что оно public я что-то вообще даже и не подумал.
нужно его private делать конечно же.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Нужно ли высвобождать память
« Ответ #6 : 13-09-2017, 15:17:49 »
А что строка
Код - C# [Выбрать]
  1. obj=null;
разве не вызовет диструктор класса?
Чего вдруг? Это тебе не lisp, в котором в этой ситуации чистится память.
И вообще сборщик мусора действительно когда-нибудь вызовет Ent.Dispose(), только тут два нюанса:
1) Ent вставлен в чертеж или нет? Если вставлен, то он должен быть вовремя закрыт, т.е. вызван его метод Close(), который равносилен вызову Dispose() в этом случае. Если не вставлен, то Dispose() просто освобождает память.
2) Сборщик мусора может запустится не в главной задаче, а это чревато Fatal Error если Ent не был вовремя закрыт (т.е. не был вызван его Dispose).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Re: Нужно ли высвобождать память
« Ответ #7 : 13-09-2017, 15:28:42 »
1) Ent вставлен в чертеж или нет?
В моем случае Entity не будет вставлен в чертеж,
Он будет просто хранится в памяти для манипуляций с ним.

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Re: Нужно ли высвобождать память
« Ответ #8 : 13-09-2017, 15:45:59 »
Т.е. надо сделать так
// Унаследоватся от Диспособла

Код - C# [Выбрать]
  1. public class Myclass: IDisposable {
  2.       bool disposed = false;
  3.       private Line Ln;
  4.      ...
  5.      // Ну пусть к примеру такой конструтор
  6.      public MyClass() {
  7.           this.Ln  = new Line(...) // Взял памяти под объект
  8.      }
  9.     public void Dispose() {
  10.         Dispose(true);
  11.         GC.SuppressFinalize(this);          
  12.      }
  13.  
  14.      protected virtual void Dispose(bool disposing)
  15.      {
  16.       if (disposed)
  17.          return;
  18.       if (disposing)
  19.          Ln.Dispose(); // Высвободил взятую память
  20.        disposed = true;
  21.      }
  22. }

И при работе с моим классом
делать так?

Код - C# [Выбрать]
  1. MyClass Obj  = new MyClass();
  2. ...
  3. Obj.Dispose();


Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Re: Нужно ли высвобождать память
« Ответ #9 : 13-09-2017, 16:49:01 »
А я еще обатил вниамение не то что у объекта
класса Entity есть функция IsDisposed

И прсто так dispose лучше не вызваать
Лучше сделать проверочку
Код - C# [Выбрать]
  1. if (Ent.IsDisposed)
  2.     Ent.Dispose();

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Нужно ли высвобождать память
« Ответ #10 : 13-09-2017, 16:56:06 »
Лучше сделать проверочку
Код - C# [Выбрать]

    if (Ent.IsDisposed)
        Ent.Dispose();
Только с точностью до наоборот. Вызывать Ent.Dispose() можно и нужно только если не Ent.IsDisposed
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Нужно ли высвобождать память
« Ответ #11 : 13-09-2017, 16:59:47 »
И при работе с моим классом
делать так?

Код - C# [Выбрать]

    MyClass Obj  = new MyClass();
    ...
    Obj.Dispose();
Можно и так, но лучше:
Код - C# [Выбрать]
  1.     using (MyClass Obj  = new MyClass())
  2.     {
  3.       //...
  4.     }
  5.  
Obj.Dispose() в явном виде тода вызывать не нужно. Он будет вызван на закрывающейся фигурной скобке.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Re: Нужно ли высвобождать память
« Ответ #12 : 13-09-2017, 17:19:17 »
Только с точностью до наоборот. Вызывать Ent.Dispose() можно и нужно только если не Ent.IsDisposed
А у меня проблема такая что когда вызваю Ln.Dispose
выдается такая ошибка:
"Попытка чтения или записи в защищенную память.
Это часто свидетельствует о том, что другая память повреждена."

Это наверное из-за того что Host Application я не создавал
и тест написал как консольное приложение.



Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Нужно ли высвобождать память
« Ответ #13 : 13-09-2017, 17:22:05 »
Это наверное из-за того что Host Application я не создавал
и тест написал как консольное приложение.
Если ты писал в стиле RealDWG, то возможно. Иначе я не понял о чем ты.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей (IdeaSoft)Автор темы

  • ADN
  • *
  • Сообщений: 1189
  • Карма: 9
    • idea-soft.ru
  • Skype: makar_govorun
Re: Нужно ли высвобождать память
« Ответ #14 : 13-09-2017, 17:23:16 »
Вот весь код консольного приложения


Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.Geometry;
  4.    
  5. namespace test_acad_Dispose
  6. {
  7.     class MyClass : IDisposable {
  8.         bool disposed = false;
  9.         private Line Ln = null;
  10.         public MyClass() {
  11.             Ln = new Line(new Point3d(0, 0, 0),
  12.                           new Point3d(1, 1, 1));
  13.         }
  14.         public void Dispose()  {
  15.             Dispose(true);
  16.             GC.SuppressFinalize(this);
  17.         }
  18.         protected virtual void Dispose(bool disposing)
  19.         {
  20.             if (disposed)
  21.                 return;
  22.             if (disposing)
  23.                 Ln.Dispose(); // Вот тут ругается
  24.             disposed = true;
  25.         }
  26.     }
  27.  
  28.     class Program
  29.     {
  30.         static void Main()
  31.         {
  32.             int cnt = 100000;
  33.             MyClass[] obj = new MyClass[cnt];
  34.             for (int i=0; i<cnt; i++)
  35.                obj[i] = new MyClass();
  36.        
  37.             for (int i = 0; i < cnt; i++)
  38.                 obj[i].Dispose();
  39.            
  40.             Console.ReadKey();
  41.        
  42.         }
  43.     }
  44. }