C # Ручное удаление указателя объекта - PullRequest
0 голосов
/ 20 сентября 2018

Почему бы не создать возможность удаления объектов в C #, как в C ++, в качестве альтернативного, но не обязательного действия?

Например, когда мы хотим очистить память из объекта 500 Мбайт после того, как больше нет необходимостине ждать GC (сборщик мусора)

Ответы [ 6 ]

0 голосов
/ 20 сентября 2018

В языках, которые позволяют явно освобождать объекты, ссылка на освобожденный объект может самопроизвольно стать, казалось бы, действительной ссылкой на не связанный объект.Например, в C, заданном:

FILE *f = fopen("file1", "w");
...
fclose(f);
FILE *g = fopen("file2", "w");
...
fprintf(f,"Hey there!");

, возможно, что к моменту выполнения fprintf FILE, обозначенный f, будет переработан для использования с file2.В целом, для языка не существует дешевого способа защиты от таких ошибок.

Одним из основных преимуществ GC на основе достижимости является то, что такая вещь просто не может произойти .Если выполняется:

someStreamType f = openStreamSomewhow(...);
f.Dispose();
someStreamType g = openStreamSomewhow(...);
f.outputData(...);

, то во время вызова outputData f будет содержать ссылку на удаленный объект потока.Пока любая копия этой ссылки существует где-либо в юниверсе, она будет продолжать идентифицировать тот же мертвый объект.

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

0 голосов
/ 20 сентября 2018

Я добавлю свои 50 центов относительно GC.Если у вас много больших неуправляемых объектов .NET не знает, что вы потребляете много памяти, и вам нужно добавить Давление памяти , чтобы уведомить, сколько байтов выделено в реальности:

GC.AddMemoryPressure(long bytes)

Пример можно найти здесь:

http://adavesh.blogspot.com/2012/02/gcaddmemorypressure-working-with-native.html

0 голосов
/ 20 сентября 2018

Вы можете использовать GC.Collect ();вызвать сборщик мусора, но обычно это не рекомендуется, если у вас нет веских причин и вы не знаете, что делаете.

Если у вас есть способ добраться до объекта, который вы хотите уничтожить, уничтожить этот объект фактически невозможно - сборщик не будет собирать объект, который доступен.

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

0 голосов
/ 20 сентября 2018

Весь смысл управляемого языка, такого как .NET, состоит в том, что существует сборщик мусора, который удаляет все потерянные объекты.Это все объекты, на которые нет ссылок.Например, в следующем примере, когда программа достигает конца метода DoSomething, все ссылки на созданный объект типа MyClass теряются, а сам объект помечается как для удаления.Однако GC решает , когда сделать это.

void SoSomething()
{
    var m = new MyClass();
}

Таким образом, вам не нужно заботиться об этом, если у вас нет неуправляемых ресурсов, с которыми GC не может справитьсявсе.

Итак, у вас, похоже, есть большая проблема с дизайном в вашей программе.У вас либо слишком много объектов в GC-состоянии 2, которые являются долгоживущими и, следовательно, не собраны (например, static переменные), либо есть много неуправляемых ресурсов, таких как обработчики файлов, которые GC не может обработать.

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

Во втором случае вы должны использовать метод Dispose для каждого такогоресурс.Это проще всего сделать с using, который автоматически вызовет IDisposable.Dipose(), когда возникает исключение или когда выполняется кодовый блок.Вызов Dispose обеспечит освобождение неуправляемой памяти.Однако оставшаяся управляемая часть объекта все еще остается в памяти.Тем не менее, это будет скоро сборщик мусора, как только все ссылки на него исчезнут, отсюда важность переменной scope.

using (FileStream fs = File.Create(path))
{
    // do something with the file
}
0 голосов
/ 20 сентября 2018

Так работает GC поколений.В отличие от C ++ в нем нет карты свободного пространства для размещения нового объекта.Он просто распределяет новые объекты в пространстве памяти после предыдущего выделения.Когда происходит GC, объекты, которые все еще должны храниться в памяти, сжимаются и физически перемещаются в памяти.

Таким образом, даже если бы вы могли освободить один объект, распределитель памяти не будет использовать этот сегмент памяти, пока не произойдет следующий GC, ибессмысленно освобождать только один объект.

Конечно, в ГХ есть больше деталей, таких как разные поколения, куча больших объектов, несколько сегментов за поколения, но в целом удаление только одного объекта бесполезно.

0 голосов
/ 20 сентября 2018

Если объект, с которым вы работаете, реализует IDisposable в своем классе, то вы можете вызвать my_object.Dispose();, чтобы вручную удалить выделение памяти.

Вы также можете принудительно запустить сборщик мусора, используя System.GC.Collect()это не рекомендуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...