C#手动删除对象指针

时间:2018-09-20 08:47:22

标签: c# garbage-collection

为什么不像在C ++中那样创建一种删除C#中对象的可能性,但这不是必需的动作?

例如,当我们要从500 Mb对象中清除内存后,就不必再等待GC(垃圾收集器)

6 个答案:

答案 0 :(得分:3)

诸如.NET之类的托管语言的全部要点是,有一个垃圾收集器可以删除所有孤立的对象。这些都是不存在引用的所有对象。例如,在下面的示例中,当程序到达DoSomething方法的末尾时,对创建的MyClass类型对象的所有引用都将丢失,并且该对象本身被标记以删除。但是,GC决定何时执行此操作。

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

因此,除非您有一些非托管资源(GC根本无法处理),否则您不必太在意。

因此,您的程序中似乎存在一些大设计问题。您要么在GC状态2中拥有太多的对象,这些对象是长期存在的并且因此没有被收集(例如,static变量),或者有许多不受管理的资源,例如GC无法处理的文件处理程序。

在第一种情况下,应尽可能限制变量的范围。

在第二种情况下,您应该为每种此类资源使用Dispose方法。使用using最容易做到这一点,当发生异常或代码块完成时,它将自动调用IDisposable.Dipose()。调用Dispose将确保释放非托管内存。但是,对象的其余 managed 部分仍保留在内存中。但是,一旦所有对它的引用都消失了,它将很快被垃圾收集,因此变量作用域的重要性。

using (FileStream fs = File.Create(path))
{
    // do something with the file
}

答案 1 :(得分:1)

您可以使用GC.Collect();强制垃圾收集器进行收集,但是通常不建议这样做,除非您有充分的理由并且知道自己在做什么。

如果您有办法到达要销毁的对象,则实际上不可能销毁该对象-收集器将不会收集可到达的对象。

如果您要销毁的对象是非托管对象,请使用或将其包装处理。

答案 2 :(得分:1)

我将为我的GC增加50美分。如果您有很多大型的非托管对象,.NET不知道您占用了太多内存,则需要添加Memory Pressure来通知实际上分配了多少字节:

GC.AddMemoryPressure(long bytes)

可以在此处找到示例:

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

答案 3 :(得分:0)

如果要使用的对象在其类中实现IDisposable,则可以调用my_object.Dispose();来手动删除内存分配。

尽管不建议这样做,但也可以强制垃圾收集器使用System.GC.Collect()运行。

答案 4 :(得分:0)

这是世代GC的工作方式。与C ++不同,它没有可用空间映射来分配新对象。它只是在先前分配之后在内存空间中分配新对象。当发生GC时,仍然需要保留在内存中的对象将被压缩并以物理方式移动到内存中。

因此,即使可以释放单个对象的内存分配器也不会在下一次GC发生之前使用该内存段,并且仅释放一个对象是没有意义的。

当然,GC中还有更多详细信息,例如不同的世代,大型对象堆,世代相传的多个段,但是总体上只删除一个对象是没有用的。

答案 5 :(得分:0)

在允许显式释放对象的语言中,对释放对象的引用有可能自发地成为对无关对象的看似有效的引用。例如,在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将保留对已处置流对象的引用。只要该引用的任何副本存在于Universe中的任何位置,它将继续标识相同的死对象。

除非Java和.NET可以确定对象的引用不存在,否则它们都不能安全地回收该对象使用的存储。同时对大量对象进行这样的确定要比对单个对象进行确定要便宜得多,因此被告知可能不存在对某些特定对象的引用并不是很有帮助。