简体   繁体   English

在C#中销毁一个struct对象?

[英]Destroying a struct object in C#?

I am a bit confused about the fact that in C# only the reference types get garbage collected. 我有点困惑的是,在C#中只有引用类型被垃圾收集。 That means GC picks only the reference types for memory de-allocation. 这意味着GC只选择内存解除分配的引用类型。 So what happens with the value types as they also occupy memory on stack ? 那么值类型会发生什么呢?因为它们也会占用堆栈上的内存?

For a start, whether they're on the stack or part of the heap depends on what context they're part of - if they're within a reference type, they'll be on the heap anyway. 首先,它们是在堆栈还是堆的一部分取决于它们所属的上下文 - 如果它们在引用类型中,它们无论如何都会在堆上。 (You should consider how much you really care about the stack/heap divide anyway - as Eric Lippert has written, it's largely an implementation detail .) (无论如何,你应该考虑你真正关心堆栈/堆分裂的程度 - 正如Eric Lippert写的那样,它主要是一个实现细节 。)

However, basically value type memory is reclaimed when the context is reclaimed - so when the stack is popped by you returning from a method, that "reclaims" the whole stack frame. 但是,回收上下文时基本上会回收值类型内存 - 因此当您从方法返回时弹出堆栈时,“回收”整个堆栈帧。 Likewise if the value type value is actually part of an object, then the memory is reclaimed when that object is garbage collected. 同样,如果值类型值实际上是对象的一部分,则在该对象被垃圾回收时回收内存。

The short answer is that you don't have to worry about it :) (This assumes you don't have anything other than the memory to worry about, of course - if you've got structs with references to native handles that need releasing, that's a somewhat different scenario.) 简短的回答是你不必担心它:)(这假设除了内存之外你没有其他任何事情要担心,当然 - 如果你有结构引用需要释放的本机句柄,这是一个有点不同的情况。)

I am a bit confused about the fact that in C# only the reference types get garbage collected. 我有点困惑的是,在C#中只有引用类型被垃圾收集。

This is not a fact. 这不是事实。 Or, rather, the truth or falsity of this statement depends on what you mean by "get garbage collected". 或者说,这个陈述的真实性或虚假性取决于“收集垃圾”的含义。 The garbage collector certainly looks at value types when collecting; 垃圾收集器在收集时肯定会查看值类型; those value types might be alive and holding on to a reference type: 这些值类型可能存在并保持引用类型:

struct S { public string str; }
...
S s = default(S); // local variable of value type
s.str = M(); 

when the garbage collector runs it certainly looks at s, because it needs to determine that s.str is still alive. 当垃圾收集器运行时,它肯定会查看s,因为它需要确定s.str仍然存活。

My suggestion: clarify precisely what you mean by the verb "gets garbage collected". 我的建议:用动词“收集垃圾”来准确澄清你的意思。

GC picks only the reference types for memory de-allocation. GC仅选择内存解除分配的引用类型。

Again, this is not a fact. 同样,这不是事实。 Suppose you have an instance of 假设你有一个实例

class C { int x; }

the memory for the integer will be on the garbage-collected heap, and therefore reclaimed by the garbage collector when the instance of C becomes unrooted. 整数的内存将位于垃圾收集堆上,因此当C实例无根时由垃圾收集器回收。

Why do you believe the falsehood that only the memory of reference types is deallocated by the garbage collector? 为什么你会相信垃圾收集器只释放引用类型的内存? The correct statement is that memory that was allocated by the garbage collector is deallocated by the garbage collector, which I think makes perfect sense. 正确的说法是由垃圾收集器分配的内存由垃圾收集器释放 ,我认为这是完全合理的。 The GC allocated it so it is responsible for cleaning it up. GC分配它,因此它负责清理它。

So what happens with the value types as they also occupy memory on stack ? 那么值类型会发生什么呢?因为它们也会占用堆栈上的内存?

Nothing at all happens to them. 什么都没发生在他们身上。 Nothing needs to happen to them. 没有什么需要发生在他们身上。 The stack is a million bytes. 堆栈是一百万字节。 The size of the stack is determined when the thread starts up; 堆栈的大小是在线程启动时确定的; it starts at a million bytes and it stays a million bytes throughout the entire execution of the thread. 它从一百万字节开始,并且在整个线程执行期间保持一百万字节。 Memory on the stack is neither created nor destroyed; 堆栈中的内存既不会被创建也不会被破坏; only its contents are changed. 只是它的内容被改变了。

There are too many verbs used in this question, like destroyed, reclaimed, deallocated, removed. 此问题中使用的动词太多,如已销毁,已回收,已取消分配,已删除。 That doesn't correspond well with what actually happens. 这与实际发生的情况不符。 A local variable simply ceases to be, Norwegian parrot style . 一个局部变量根本不再是挪威鹦鹉风格

A method has a single point of entry, first thing that happens is that the CPU stack pointer is adjusted. 一个方法有一个单一的入口点,首先发生的是调整CPU堆栈指针。 Creating a "stack frame", storage space for the local variables. 创建“堆栈框架”,为局部变量创建存储空间。 The CLR guarantees that this space is initialized to 0, not otherwise a feature you use strongly in C# because of the definite assignment rule. CLR保证将此空间初始化为0,而不是由于明确的赋值规则而在C#中强烈使用的功能。

A method has a single point of exit, even if you method code is peppered with multiple return statements. 即使方法代码中包含多个return语句,方法也只有一个退出点。 At that point, the stack pointer is simply restored to its original value. 此时,堆栈指针简单地恢复到其原始值。 In effect it "forgets" that the local variables where ever there. 实际上它“忘记”了那里的局部变量。 Their values are not 'scrubbed' in any way, the bytes are still there. 它们的值不以任何方式“擦除”,字节仍然存在。 But they won't last long, the next call in your program are going to overwrite them again. 但它们不会持续很长时间,程序中的下一个调用将再次覆盖它们。 The CLR zero-initialization rule ensures that you can never observe those old values, that would be insecure. CLR零初始化规则确保您永远不会观察那些不安全的旧值。

Very, very fast, takes no more than a single processor cycle. 非常非常快,只需一个处理器周期。 A visible side-effect of this behavior in the C# language is that value types cannot have a finalizer. C#语言中此行为的可见副作用是值类型不能具有终结器。 Ensuring no extra work has to be done. 确保不必进行额外的工作。

当堆栈超出范围时,堆栈中的值类型将从堆栈中删除。

值类型一旦超出范围就会被销毁。

我会假设在执行堆栈帧后删除堆栈帧时,将取消分配值类型

Would also like to add that stack is at a thread level, and heap is at application domain level. 还要添加堆栈处于线程级别,堆处于应用程序域级别。

So, when a thread ends it would reclam the stack memory used by that specific thread. 因此,当一个线程结束时,它将重新启动该特定线程使用的堆栈内存。

Every value type instance in .NET will be part of something else, which could be a larger enclosing value type instance, a heap object, or a stack frame. .NET中的每个值类型实例都将成为其他内容的一部分,这可能是更大的封闭值类型实例,堆对象或堆栈帧。 Whenever any of those things come into being, any structures within them will also come into being; 每当这些东西出现时,其中的任何结构也会形成; those structures will then continue to exist as long as the thing containing them does. 只要包含它们的东西确实存在,那么这些结构将继续存在。 When the thing that contains the structure ceases to exist, the structure will as well. 当包含结构的东西不再存在时,结构也将如此。 There is no way to destroy a structure without destroying the container, and there is no way to destroy something that contains one or more structures without destroying the structures contained therein. 没有破坏容器就无法破坏结构,并且没有办法破坏包含一个或多个结构的东西而不破坏其中包含的结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM