Я не знаком с деталями сборки мусора D, но общая техника состоит в том, чтобы начинать со всех «корневых указателей», чтобы выяснить, какие объекты являются живыми.Когда все скомпилировано в машинный код, это означает, что он начинается со стека вызовов функций и регистров ЦП.
Приведенный выше код может компилироваться в нечто вроде:
$r0 = new C("c1")
$r0 = new C("c2")
GC.collect()
writeln("Running second round GC.collect")
GC.collect()
writeln("Exiting...")
Когда первыйGC.collect()
больше нет ссылок на первый объект (так как $r0
был перезаписан).И хотя второй объект не используется, в $r0
все еще есть указатель на него, поэтому GC консервативно предполагает, что он достижим.Обратите внимание, что компилятор мог предположительно очистить $r0
после того, как переменная c2
выйдет из области видимости, но это сделает код более медленным.
Когда выполняется первый вызов writeln
, он, вероятно, использует регистр $r0
внутренне и поэтому очищает ссылку на второй объект.Вот почему второй объект восстанавливается после второго вызова GC.collect()
.