О мусоре бедном замолвите слово
От: Кодт Россия  
Дата: 17.10.02 12:22
Оценка: 25 (2) +1
Не о милицанере А об освобождении ресурсов.

Внесите ясность в мою голову, пожалуйста.



Система предоставляет разнообразные ресурсы (например, память на куче).
Приложение их берет, пользуется и возвращает.

Низкий уровень:
...
handle_t h = allocate(...);
...
use(h)...
...
release(h);
...

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

Для ресурса типа "память" есть различные методы сборки мусора:
— моментальный (умные указатели различных видов)
— отложенный (специальная организация кучи + умные указатели поддерживаемые компилятором)

А как быть с другими ресурсами, например, с файлами?

На C++ это решается с помощью умного хэндлера, который в деструкторе делает что-то полезное.
В сочетании с моментальной уборкой мусора это прекрасно работает.

Так почему же Java, C#, MC отказались от этого, оставляя программисту исключительно вручную управлять каждым экземпляром ресурса?
В лучшем случае автоматизировать можно обработку исключений
File* pFile = 0;
Mutex* pMutex = 0;
__try
{
  pFile = new File("hello.txt", "rw+");
  pMutex = new Mutex();

  ...

}
__finally
{
  if(pFile) pFile->close();
  if(pMutex) pMutex->destroy();
}
// судьбой указателей и объектов-оберток займется мусоросборщик

Такие фокусы возможны только в ограниченном контексте (например, в теле функции).

Если какой-то объект содержит не только подчиненные объекты (этим занимается мусоросборщик), но еще и какие-то ресурсы в этих объектах или в самом себе, то этот объект должен иметь функцию финализации
class CompoundResource
{
  File* m_pFile;
  Mutex* m_pMutex;
  HANDLE m_hDllModule;
public:
  void finalize()
  {
    if(m_pFile)      { m_pFile->close(); m_pFile = NULL; }
    if(m_pMutex)     { m_pMutex->destroy(); m_pMutex = NULL; }
    if(m_hDllModule) { FreeLibrary(m_hDllModule); m_hDllModule = NULL; }
  }
  ...
};

Получается, мы сочинили псевдо-деструктор, который будем вызывать вручную!
А если не вызывать — то эти ресурсы прокукуют как минимум до сборки мусора, где сборщик вызовет настоящий деструктор (в котором вызывается эта функция финализации) — а если алгоритм икнет — то вообще до конца процесса. А, по последним сведениям, .net-овский алгоритм икает.

Ну и что мы тогда выигрываем?
+ Избавились от глупых/умных указателей, от потерь памяти, от проблемы кольцевых ссылок (главный враг моментального сборщика мусора, как например, COM)
— Пришли к необходимости ручной финализации. Дожили!

И не надо говорить, что это надуманная проблема, что рано или поздно процесс завершится и отдаст все концы.
Серверное приложение может отлично выжрать весь лимит открытых файлов, после чего ОС пошлет всех на.



Где же выход?
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.