Реализация объекта в деструкторе того же класса и сборщика мусора - PullRequest
1 голос
/ 21 июня 2011

Недавно, когда я занимался вводным блоком, посвященным объектно-ориентированному программированию, я познакомился с сборщиком мусора в C #, и его роль заключается в «очистке» объектов, на которые больше нет ссылок. Затем я познакомился с деструкторами и с тем, как они называются непосредственно перед удалением объекта.

Естественно, я задумался, но никогда не вспоминал, чтобы спросить об этом лектора; что произойдет, если вы создадите экземпляр класса в деструкторе того же класса?

C # пример

class Person{
 ~Person(){

  Person p = new Person();
  Console.WriteLine("Person destroyed");

 }
}

class Program{
 static void Main(string[] args){
  Person p = new Person();
 }
}

Я хотел бы подойти к этому с более теоретической точки зрения, поэтому я неохотно (на данном этапе) пробую это, так как я, вероятно, все равно не пойму, но у меня есть несколько теорий. Кроме того, я сейчас не за своим обычным компьютером;)

  • Person. ~ Person () будет выполнять рекурсию, так как каждый раз, когда создается новый Person, он вызывает его деструктор и создает нового Person до бесконечности, или пока не произойдет какое-то исключение, связанное с памятью. Впоследствии main никогда не прекратит работу.
  • Компилятор будет жаловаться (в любом случае добавление этой опции в каждый сценарий кажется хорошей идеей).
  • Каким-то образом произойдет какой-то "пропуск деструктора". то есть. уничтожение объекта не будет вызываться последовательно, поэтому не будет и конструктор.

Теперь к аналогичному вопросу. Если роль сборщика мусора заключается в удалении объектов, на которые больше нет ссылок / необходимости, как будет обрабатываться ситуация, подобная описанной выше, в среде без сборщика мусора, скажем, C ++?

Ответы [ 3 ]

4 голосов
/ 21 июня 2011

Здесь, на мой взгляд, нет никакой настоящей загадки.

Это не «рекурсивно» как таковое - вы просто бросаете новый объект в управляемую кучу, который немедленно разыменовывается;что делает его кандидатом на сборку мусора.

В конце концов сборщик мусора снова возвращается в исходное состояние, снова вызывая операцию и т. д.

Это не рекурсия - больше похоже на цепочку.Но в конечном итоге каждый Person будет удален из памяти.

И через некоторое время сборщик мусора отправит вам электронное письмо с жалобой, что вы не играете честно.

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

Если ваша следующая логическая мысль: «Разве среда выполнения / язык не должны помешать этому случиться?'- нетРассматриваемый язык или среда выполнения не предназначены для того, чтобы помешать вам сделать что-то, что в противном случае было бы сочтено необоснованным;вам, программисту, нужно быть уверенным, что вы этого не делаете.

Тем не менее, в сценарии завершения работы приложения (см. ваш комментарий ниже) среда выполнения .Net будет действовать из собственных интересов.и в конечном итоге прекратит обработку этих финализаторов для завершения работы.Финализаторы для вашей выгоды, а не для среды выполнения.

2 голосов
/ 21 июня 2011

Еще один интересный момент: объект 1001 * может воскресить себя в финализаторе!

class Foo
{
    static public List<Foo> ZombieFoos = new List<Foo>;

    ~Foo()
    {
        ZombieFoos.Add(this);

        // Now there is a reference to this instance again (in the list)..
        // The GC will not reclaim this instance.. huzzah we have been resurrected!!
    }
}

Даже отдаленно не рекомендуется ...

1 голос
/ 21 июня 2011

Вы могли бы фактически заставить систему работать в GC 99,9 раз. Просто приобретите достаточный объем памяти каждым объектом Person для GC, чтобы запустить сборник Heap 0.

...