Многие языки, такие как Java, Python, Go, C# и т. д., имеют встроенные сборщики мусора, но в примитивных языках, таких как C/C++, их нет. Мы создадим сборку мусора с помощью подсчета ссылок на C++.

Область статьи

  • Что такое сбор мусора? Зачем они нам нужны?
  • Почему в C/C++ отсутствует сборка мусора?
  • Можем ли мы построить один?
  • Сбор мусора через подсчет ссылок

Введение. Что такое сборка мусора? Зачем они нам нужны?

В первом разделе мы рассмотрим, что такое сборка мусора и зачем она нужна.

Наши программы используют память в виде переменных и объектов. Объекты размещаются либо в стеке, либо в куче. В стеках хранятся локально объявленные переменные, такие как «int a = 10;» в кадре стека функции, поэтому, когда функция возвращает значения, они извлекаются из кадра стека, делая их несуществующими. Так что нам не нужна сборка мусора для стека.

Кучи, с другой стороны, разные. Переменная кучи выделяется с помощью функций «new» или «malloc». Объектное пространство, созданное для таких вещей, находится в оперативной памяти. Они должны быть явно освобождены, когда мы закончим с ними, поскольку они переживут область действия и выполнение функции. Для кучи нам нужна функция автоматического восстановления памяти, встроенная в языки программирования, называемая сборщиками мусора. Отсутствие сборщика мусора может привести к утечкам памяти и оборванным указателям.

Почему в C/C++ отсутствует сборка мусора?

  1. Производительность. Сборка мусора может быть ресурсоемкой и может негативно сказаться на производительности программы. В C/C++ разработчики могут вручную управлять памятью, что может привести к более эффективному использованию ресурсов. C/C++ должен работать на «голом железе» с быстрым временем выполнения.
  2. Контроль: C/C++ позволяет разработчикам полностью контролировать выделение и освобождение памяти, позволяя им оптимизировать свой код для конкретных случаев использования. При сборке мусора у разработчиков может быть меньше контроля над выделением и освобождением памяти.
  3. Совместимость: C/C++ часто используется для написания низкоуровневых системных библиотек и драйверов, которые требуют точного контроля над управлением памятью. Сборка мусора может быть несовместима с этими типами приложений.
  4. Сложность. Реализация сборки мусора на C/C++ может быть сложной, так как требует добавления в язык дополнительного кода. Это может увеличить сложность языка и может не стоить усилий для некоторых разработчиков.
  5. Устаревший код: C/C++ существует уже давно и имеет большое количество существующих кодовых баз, основанных на ручном управлении памятью. Добавление сборки мусора в язык потенциально может сломать эти основы кода и вызвать проблемы у разработчиков, которые на них полагаются.

Можем ли мы построить его?

Да, можно построить систему сборки мусора для C/C++. Существует несколько сторонних библиотек, предлагающих сборку мусора для C/C++, например сборщик мусора Boehm-Demers-Weiser. Однако эти системы могут работать не со всем кодом C/C++ и могут иметь некоторые потери производительности по сравнению с ручным управлением памятью. Кроме того, реализация сборки мусора в C/C++ может быть более сложной и требовать больше усилий, чем в языках, которые имеют встроенную поддержку сборки мусора.

В C и C++ вы можете реализовать сборку мусора, используя подсчет ссылок, маркировку и очистку, отслеживание сборки мусора и т. д.

Бонус: сборка мусора с помощью подсчета ссылок.

#include <iostream>
#include <unordered_map>
#include <memory>

// A simple garbage collected object
class GCObject {
public:
    // Constructor increments the reference count
    GCObject() : refCount(1) {}

    // Destructor decrements the reference count
    virtual ~GCObject() {
        refCount--;
        // If the reference count is 0, delete the object
        if (refCount == 0) {
            delete this;
        }
    }

    // Increment the reference count
    void AddRef() {
        refCount++;
    }

private:
    int refCount;
};

// A garbage collector class
class GC {
public:
    // Add an object to the garbage collector
    static void AddObject(GCObject* obj) {
        objects[obj] = obj;
    }

    // Remove an object from the garbage collector
    static void RemoveObject(GCObject* obj) {
        objects.erase(obj);
    }

    // Collect garbage by deleting objects with a reference count of 0
    static void Collect() {
        for (auto& [obj, count] : objects) {
            if (obj->refCount == 0) {
                delete obj;
            }
        }
    }

private:
    static std::unordered_map<GCObject*, GCObject*> objects;
};

// Initialize the static objects map
std::unordered_map<GCObject*, GCObject*> GC::objects;

int main() {
    // Create a garbage collected object
    GCObject* obj = new GCObject();

    // Add the object to the garbage collector
    GC::AddObject(obj);

    // Remove the object from the garbage collector
    GC::RemoveObject(obj);

    // Collect garbage
    GC::Collect();

    return 0;
}

В этом классе GCObject реализуется подсчет ссылок путем поддержки поля refCount. Конструктор GCObject увеличивает счетчик ссылок, а деструктор уменьшает его. Если счетчик ссылок становится равным 0, объект удаляет себя.

Класс GC — это простой сборщик мусора, который поддерживает карту объектов и количество их ссылок. Методы AddObject и RemoveObject добавляют и удаляют объекты с карты соответственно. Метод Collect перебирает объекты на карте и удаляет все объекты со счетчиком ссылок, равным 0.

В двух словах…

В заключение, хотя сборка мусора может быть полезным инструментом для управления памятью в языках программирования, она может отрицательно сказаться на производительности и может быть несовместима с некоторыми типами приложений. Разработчики C/C++ имеют возможность вручную управлять памятью, что может обеспечить больший контроль и потенциально более эффективное использование ресурсов. Однако реализация сборки мусора в C/C++ может быть сложной и не стоит затраченных усилий для некоторых разработчиков. Кроме того, большое количество устаревших кодовых баз, которые полагаются на ручное управление памятью в C/C++, могут создать проблемы для включения сборки мусора в язык.