Где сделал переменную = пустой указатель как, “уничтожение объекта” прибывает из?

Работая в ряде унаследованных систем, записанных в различных версиях.NET, через многие различные компании, я продолжаю находить примеры следующего шаблона:

public void FooBar()
{
    object foo = null;
    object bar = null;

    try
    {
       foo = new object();
       bar = new object();

       // Code which throws exception.
    }
    finally
    {
       // Destroying objects
       foo = null;
       bar = null;
    }

}

Кому-либо, который знает, как работы управления памятью в.NET, этот вид кода является крайне ненужным; для сборщика "мусора" не нужны Вы для ручного присвоения null сказать, что старый объект может быть собран, ни делает присвоение null сообщает GC к сразу собранному объект.

Этот шаблон является просто шумом, мешая понимать то, чего код пытается достигнуть.

Да ведь затем, я продолжаю находить этот шаблон? Существует ли школа, которая преподает эту практику? Есть ли язык в который присвоение null значения к локально ограниченным по объему переменным требуются, чтобы правильно управлять памятью? Есть ли в явном присвоении некоторое дополнительное значение null то, что я не чувствовал?

22
задан Paul Turner 28 June 2010 в 12:45
поделиться

14 ответов

Это FUD программирование культа груза (благодаря Дэниелу Эрвикеру ) разработчиками, которые привыкли «освобождать» ресурсы, плохие реализации GC и плохой API.

Некоторые GC не справлялись с циклическими ссылками. Чтобы избавиться от них, нужно было «где-то разорвать круг». Где? Ну если сомневаетесь, то везде. Делайте это в течение года, и это перейдет в ваши руки.

Также установка поля на null дает вам идею «что-то делать», потому что, как разработчики, мы всегда боимся «что-то забыть».

Наконец, у нас есть API-интерфейсы, которые должны быть закрыты явно, потому что нет реальной языковой поддержки, чтобы сказать «закройте это, когда я закончу с этим», и пусть компьютер сам разберется, как с GC. Итак, у вас есть API, в котором вам нужно вызывать код очистки, и API, где у вас его нет. Это отстой и поощряет модели, подобные приведенным выше.

22
ответ дан 29 November 2019 в 04:44
поделиться

Разработчики VB должны были избавиться от всех своих объектов, чтобы попытаться уменьшить вероятность утечки памяти. Я могу представить, откуда он появился, когда разработчики VB перешли на .NEt / c #

0
ответ дан 29 November 2019 в 04:44
поделиться

Возможно, соглашение о присвоении null возникло из-за того, что если бы foo был переменной экземпляра вместо локальной переменной, вам следует удалить ссылку, прежде чем сборщик мусора сможет ее собрать. . Кто-то заснул во время первого предложения и начал обнулять все их переменные; толпа последовала за ним.

1
ответ дан 29 November 2019 в 04:44
поделиться

Я много раз видел это в коде VBScript (классический ASP), и я думаю, что это исходит оттуда.

2
ответ дан 29 November 2019 в 04:44
поделиться

Это чаще встречается в языках с детерминированной сборкой мусора и без RAII, таких как старый Visual Basic, , но даже там это не нужно , и там часто приходилось ломать циклические ссылки. Так что, возможно, это действительно связано с плохими программистами на C ++, которые повсюду используют тупые указатели. В C ++ имеет смысл установить для немых указателей значение 0 после их удаления, чтобы предотвратить двойное удаление.

3
ответ дан 29 November 2019 в 04:44
поделиться

Это происходит из C / C ++, где выполнение free () / delete для уже выпущенного указателя могло привести к сбою, в то время как освобождение NULL-указателя просто ничего не дало.

Это означает, что эта конструкция (C ++) вызовет проблемы

void foo()
{
  myclass *mc = new myclass(); // lets assume you really need new here
  if (foo == bar)
  {
    delete mc;
  }
  delete mc;
}

, в то время как она будет работать

void foo()
{
  myclass *mc = new myclass(); // lets assume you really need new here
  if (foo == bar)
  {
    delete mc;
    mc = NULL;
  }
  delete mc;
}

Заключение: ИТ совершенно не нужны для C #, Java и почти любого другого языка сбора мусора.

1
ответ дан 29 November 2019 в 04:44
поделиться

Это происходит из C / C ++, где явная установка для ваших указателей значения NULL была нормой (чтобы исключить висячих указателей )

После вызова free ():

#include <stdlib.h>
{
    char *dp = malloc ( A_CONST );

    // Now that we're freeing dp, it is a dangling pointer because it's pointing
    // to freed memory
    free ( dp );

    // Set dp to NULL so it is no longer dangling
    dp = NULL;
}

Классические разработчики VB также поступали так же при написании своих COM-компонентов, чтобы предотвратить утечку памяти.

3
ответ дан 29 November 2019 в 04:44
поделиться

Возможно, он пришел из VB, который использовал стратегию подсчета ссылок для управления памятью и времени жизни объекта. Установка ссылки на Nothing (эквивалент null) уменьшит счетчик ссылок. Как только этот счетчик становится равным нулю, объект синхронно уничтожается. Счетчик будет автоматически уменьшаться при выходе из области действия метода, поэтому даже в VB этот метод был в основном бесполезен, однако были особые ситуации, когда вам нужно было жадно уничтожить объект, как показано в следующем коде.

Public Sub Main()
  Dim big As Variant
  Set big = GetReallyBigObject()
  Call big.DoSomething
  Set big = Nothing
  Call TimeConsumingOperation
  Call ConsumeMoreMemory
End Sub

В приведенном выше коде объект, на который ссылается big , задержался бы до конца без вызова Set big = Nothing . Это может быть нежелательно, если другие вещи в методе были трудоемкими операциями или создавали дополнительную нагрузку на память.

8
ответ дан 29 November 2019 в 04:44
поделиться

Я думаю, что раньше это было обычным недоразумением среди бывших разработчиков C / C ++. Они знали, что сборщик мусора освободит их память, но не понимали, когда и как. Просто очистите его и продолжайте :)

2
ответ дан 29 November 2019 в 04:44
поделиться

Я подозреваю, что этот паттерн возникает из-за перевода кода C++ на C# без паузы, чтобы понять различия между финализацией C# и финализацией C++. В C++ я часто обнуляю вещи в деструкторе, либо в целях отладки (чтобы вы могли увидеть в отладчике, что ссылка больше не действительна), либо, редко, потому что я хочу, чтобы умный объект был освобожден. (Если смысл в этом, я лучше вызову Release на нем и сделаю смысл кода кристально ясным для сопровождающих). Как вы заметили, в C# это практически бессмысленно.

В VB/VBScript вы тоже постоянно видите этот паттерн, по разным причинам. Я немного размышлял о том, что может быть причиной этого здесь:

http://blogs.msdn.com/b/ericlippert/archive/2004/04/28/122259.aspx

2
ответ дан 29 November 2019 в 04:44
поделиться

Рассмотрим небольшая модификация:

public void FooBar() 
{ 
    object foo = null; 
    object bar = null; 

    try 
    { 
       foo = new object(); 
       bar = new object(); 

       // Code which throws exception. 
    } 
    finally 
    { 
       // Destroying objects 
       foo = null; 
       bar = null; 
    } 
    vavoom(foo,bar);
} 

Автор (ы), возможно, хотел убедиться, что великий Vavoom (*) не получал указатели на искаженные объекты, если ранее было сгенерировано и перехвачено исключение. Паранойя, приводящая к защитному кодированию, не обязательно плохо в этом бизнесе.

(*) Если вы знаете, кто он, вы знаете.

1
ответ дан 29 November 2019 в 04:44
поделиться

Это происходит из кода C ++, особенно интеллектуальных указателей . В этом случае это примерно эквивалентно .Dispose () в C #.

Это плохая практика, в лучшем случае инстинкт разработчика. Нет никакого реального значения путем присвоения null в C #, за исключением того, что это может помочь GC разорвать циклическую ссылку.

-4
ответ дан 29 November 2019 в 04:44
поделиться

Я вижу, что это происходит либо из-за неправильного понимания того, как работает сборка мусора, либо из-за попытки заставить сборщик мусора немедленно сработать - возможно, из-за объектов foo и bar довольно большие.

0
ответ дан 29 November 2019 в 04:44
поделиться

Я уже видел это в каком-то Java-коде раньше. Он использовался в статической переменной, чтобы сигнализировать о том, что объект должен быть уничтожен.

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

0
ответ дан 29 November 2019 в 04:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: