А мне то же пришлось сделать сборщик мусора.
Для расширения функциональности своей программы (когда то давно) я написал собственный язык программирования. Было два главных требования - любая программа на этом языке не должна была приводить к падению всей системы, и язык должен работать с классами и объектами написанными на C++. А главная причина падения - это указатели, поэтому и возникло решение сделать сборщик мусора в стиле Java или .NET.
Объекты программы могут иметь, и более того имеют кольцевые зависимости. Поэтому подсчет ссылок для такой модели не работает. Я реализовал стандартный обход графа, который описан в Википедии, поэтому вдаваться в подробности не буду.
Но способ этот медленный, значительно медленнее подсчета ссылок. Поэтому я написал анализатор кода программы, который определяет, у каких объектов могут возникать кольцевые зависимости. И если объект чист, то для него работает быстрый подсчет ссылок.
Но для кода написанного на C++ (тем более не мной), организовать подсчет ссылок было невозможно. Поэтому, если такой код используется скриптовым языком, то невозможно определить, используется ли объект в данный момент или нет. Надо было все переписывать или делать костыль.
По ходу выполнения программы объекты C++ могут помечаться на уничтожение, но уничтожаются только когда программа завершила выполнение (удаляются в цикле обработки сообщений). Это работает, причем быстрее прошлых двух способов. Но есть и минусы. При "особом уличном программировании"памяти расходуется очень много. Это уже третий способ уничтожения объектов.
Основная проблема ООП и сборщиков мусора в том, что программа создает миллиард объектов. А не в сборщике мусора конкретно. С++ умеет из коробки обходить эту проблему. Внутри объекта можно разместить сотню зависимых объектов и память под них выделится одним блоком.
То есть вместо
Писать
Но сборщик мусора не сможет корректно удалить такой объект. Поэтому в каждом объекте был размещен указатель на главный объект, который удалялся только если необходимо было удалить все объекты. То есть программа могла держать указатель на button1. И форма при этом не разрушалась, даже если на форму указателей не было.
Это уже четвертое решение по сборке мусора.
Но есть и пятое решение - это размещение объектов в стеке. И тут есть очевидная проблема. Если на момент выхода из функции и разрушения объекта, кто то сохранил на него указатель, то ни одно решение выше не поможет. Всё в итоге упадет. (Контроль того, что кто то сохранил указатель происходит по счетчику ссылок.)
Поэтому была написана еще одна программа, которая пытается занулить эти указатели. Сделать она это может лишь в скриптовом языке и тот в худшем случае отделается исключением NULL Object. Ну а если это C++ сохранил указатель, то вся программа завершается с ошибкой и указанием номера строки.
Итого:
1) Подсчет ссылок
2) Обход графа
3) Удаление объектов в цикле обработки сообщений
4) Объединение объектов в один блок
5) Размещение объектов в стеке.
Вот такой монстроидальный сборщик мусора получился при попытке скрестить: язык типа Java, язык типа C++ и скорость работы.
Для расширения функциональности своей программы (когда то давно) я написал собственный язык программирования. Было два главных требования - любая программа на этом языке не должна была приводить к падению всей системы, и язык должен работать с классами и объектами написанными на C++. А главная причина падения - это указатели, поэтому и возникло решение сделать сборщик мусора в стиле Java или .NET.
Объекты программы могут иметь, и более того имеют кольцевые зависимости. Поэтому подсчет ссылок для такой модели не работает. Я реализовал стандартный обход графа, который описан в Википедии, поэтому вдаваться в подробности не буду.
Но способ этот медленный, значительно медленнее подсчета ссылок. Поэтому я написал анализатор кода программы, который определяет, у каких объектов могут возникать кольцевые зависимости. И если объект чист, то для него работает быстрый подсчет ссылок.
Но для кода написанного на C++ (тем более не мной), организовать подсчет ссылок было невозможно. Поэтому, если такой код используется скриптовым языком, то невозможно определить, используется ли объект в данный момент или нет. Надо было все переписывать или делать костыль.
По ходу выполнения программы объекты C++ могут помечаться на уничтожение, но уничтожаются только когда программа завершила выполнение (удаляются в цикле обработки сообщений). Это работает, причем быстрее прошлых двух способов. Но есть и минусы. При "особом уличном программировании"памяти расходуется очень много. Это уже третий способ уничтожения объектов.
Основная проблема ООП и сборщиков мусора в том, что программа создает миллиард объектов. А не в сборщике мусора конкретно. С++ умеет из коробки обходить эту проблему. Внутри объекта можно разместить сотню зависимых объектов и память под них выделится одним блоком.
То есть вместо
class Form1 { Button* button1; Form1() { button1 = new Button; } }
Писать
class Form1 { Button button1; }
Но сборщик мусора не сможет корректно удалить такой объект. Поэтому в каждом объекте был размещен указатель на главный объект, который удалялся только если необходимо было удалить все объекты. То есть программа могла держать указатель на button1. И форма при этом не разрушалась, даже если на форму указателей не было.
class Form1 { Button button1; Form1() : button1(this) {} }
Это уже четвертое решение по сборке мусора.
Но есть и пятое решение - это размещение объектов в стеке. И тут есть очевидная проблема. Если на момент выхода из функции и разрушения объекта, кто то сохранил на него указатель, то ни одно решение выше не поможет. Всё в итоге упадет. (Контроль того, что кто то сохранил указатель происходит по счетчику ссылок.)
Поэтому была написана еще одна программа, которая пытается занулить эти указатели. Сделать она это может лишь в скриптовом языке и тот в худшем случае отделается исключением NULL Object. Ну а если это C++ сохранил указатель, то вся программа завершается с ошибкой и указанием номера строки.
Итого:
1) Подсчет ссылок
2) Обход графа
3) Удаление объектов в цикле обработки сообщений
4) Объединение объектов в один блок
5) Размещение объектов в стеке.
Вот такой монстроидальный сборщик мусора получился при попытке скрестить: язык типа Java, язык типа C++ и скорость работы.