昨天,我们讨论了垃圾收集。
讨论过使用Classes创建的对象被Garbage collector回收,但是使用struct创建的对象不能被GC回收
我知道结构使用堆栈,类使用堆。
但是,我猜 GC 永远不会只收集非托管代码。这是否意味着结构类型是非托管代码。(我不这么认为)。
还是 GC 只处理堆而不处理堆栈?
如果是,那么 int 数据类型呢?int 是结构而不是类。那么如果我们定义了int类型的对象,是不是被GC管理了呢?
昨天,我们讨论了垃圾收集。
讨论过使用Classes创建的对象被Garbage collector回收,但是使用struct创建的对象不能被GC回收
我知道结构使用堆栈,类使用堆。
但是,我猜 GC 永远不会只收集非托管代码。这是否意味着结构类型是非托管代码。(我不这么认为)。
还是 GC 只处理堆而不处理堆栈?
如果是,那么 int 数据类型呢?int 是结构而不是类。那么如果我们定义了int类型的对象,是不是被GC管理了呢?
如果无法从 GC 根访问它们,GC 将收集任何托管对象(并且结构是托管对象)。
但如果它是使用 struct 创建的,它不能被 GC 收集。
你被告知的内容是不正确的。托管对象的创建方式无关紧要 - 如果不再引用它,它将最终被收集。
或者这是否意味着 GC 只处理堆而不处理堆栈?
GC 负责对象图 - 如果任何 GC 根都可以访问对象,则不会收集它们,如果不是,则最终会收集它们。堆栈和堆不相关。
那么如果我们定义了int类型的对象,是不是被GC管理了呢?
int
(AKA System.Int32
) 是一个托管对象 - 一个结构。例如,如果您int
在类中声明一个字段并且该类超出范围,int
则最终将被 GC 收集。
正如@leppie 评论的那样,在许多情况下,结构将被放置在堆栈上,当堆栈被弹出时,它们将不再存在——在这种情况下,不涉及 GC(也不需要)。
如果它是使用结构创建的,它不能被 GC 收集。
不对。如果它没有被引用,它将最终被收集。
我知道结构使用堆栈,类使用堆。
这是一个普遍的误解。有关详细信息,请参阅此 Lippert 的文章。
我认为您所引用的想法是, GC通常不会收集位于堆栈上的任何数据,因为一旦程序执行离开其范围,堆栈就会被销毁。所以这意味着任何直接放入堆栈的数据(这可能意味着值类型并且应该意味着对所有其他数据的引用)将被自动清除,无需使用 GC。GC 的工作是独立于其(数据)类型清除堆数据。如果它没有被引用 - 它被收集。
But, I guess GC never collects unmanaged codes only. So is that means the Structure types are unmanaged code. (I don't think so).
I don't understand what you are asking here.
OR is that means the GC take care of Heap only not Stack?
Yes and No. GC takes care of memory required for instances of reference types (always created on the managed heap). You can view the "stack" as a piece of memory associated with current thread of execution. The stack can contain handles to reference types allocated on the managed heap. In this case the GC "cares": it will not collect the memory from the managed heap for these instances until these references on the stack exist. The stack can also contain instances (not references to!) of value types, in which case the GC does not care...
If yes, then what about int data type. int is struct not class. So if we defined the object of type int, isn't it managed by GC?
This question is a bit misleading. Let's say you "allocate" an instance of an int
on the stack:
void Foo()
{
// ...
int tTmp;
//...
}
In this case the GC does not care about tTmp
. It is placed on the current thread's stack and removed, if it gets out of scope. But if you do this:
void Foo()
{
//...
var tTmp = new int [] {
1, 2, 3, 4
};
//...
}
then the array of 4 integers is created on the managed heap and GC takes care of tTmp
. It also "indirectly" takes care of the memory required for the contents of the array, which happen to be the space required for the four integers...
Let's see what the .NET standard (ECMA-334) says
Value types differ from reference types in that variables of the value types directly contain their data, whereas variables of the reference types store references to their data, the latter being known as objects. With reference types, it is possible for two variables to reference the same object, and thus possible for operations on one variable to affect the object referenced by the other variable. With value types, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other.
In other words, there is no reason for garbage collector to care about value types, because they clean-up after themselves (when they go out of scope), they contain their own data. GC is for clean-up of shared (references) data.
Note that not only structures are value types:
A value type is either a struct type or an enumeration type. C# provides a set of predefined struct types called the simple types. The simple types are identified through reserved words.
So e.g. "int" type is so called "simple type", value type. It is bit different from other structures, because operations like +-*/ could end up being compiled into primitive operations, not function calls.