Это относится к осложнениям, связанным с более ограниченным языком Си. В C ++ вы бы просто определили базовый класс с именем GCObject
, который содержит переменные для сборки мусора, тогда TString
будет подклассом, и с помощью виртуального деструктора оба элемента TString
и сопровождающие его блоки const char *
будут освобожден должным образом.
Когда речь идет о написании такого же вида функциональности в C, это немного сложнее, так как классы и виртуальное наследование не существуют.
То, что делает Lua, реализует сборку мусора, вставляя заголовок, необходимый для управления состоянием сбора мусора части памяти, следующей за ней. Помните, что free(void *)
не нужно знать ничего, кроме адреса блока памяти.
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
Lua хранит связанный список этих «собираемых» блоков памяти, в данном случае массив символов, так что он может эффективно освободить память, не зная тип объекта, на который он указывает.
Если ваш TString
указал на другой блок памяти, в котором находился массив символов, то он требует, чтобы сборщик мусора определил тип объекта, а затем углубился в его структуру, чтобы также освободил строковый буфер.
Псевдокод для такого рода сборки мусора будет выглядеть примерно так:
GCHeader *next, *prev;
GCHeader *current = firstObject;
while(current)
{
next = current->next;
if (/* current is ready for deletion */)
{
free(current);
// relink previous to the next (singly-linked list)
if (prev)
prev->next = next;
}
else
prev = current; // store previous undeleted object
current = next;
}