内存分配:堆栈与堆?
我对堆栈与堆之间的内存分配基础知识感到困惑。根据标准定义(大家都说的),所有值类型将被分配到堆栈上,而引用类型将进入<强>堆。
现在考虑以下示例:
class MyClass
{
int myInt = 0;
string myString = "Something";
}
class Program
{
static void Main(string[] args)
{
MyClass m = new MyClass();
}
}
现在,c# 中的内存分配将如何发生? MyClass
的对象(即m
)会被完全分配到Heap吗?也就是说,int myInt
和string myString
都会进入堆?
或者,对象将被分为两部分,并被分配到两个内存位置,即堆栈和堆?
I am getting confused with memory allocation basics between Stack vs Heap. As per the standard definition (things which everybody says), all Value Types will get allocated onto a Stack and Reference Types will go into the Heap.
Now consider the following example:
class MyClass
{
int myInt = 0;
string myString = "Something";
}
class Program
{
static void Main(string[] args)
{
MyClass m = new MyClass();
}
}
Now, how does the memory allocation will happen in c#? Will the object of MyClass
(that is, m
) will be completely allocated to the Heap? That is, int myInt
and string myString
both will go to heap?
Or, the object will be divided into two parts and will be allocated to both of the memory locations that is, Stack and Heap?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
每次创建对象时,它都会进入称为堆的内存区域。原始变量如
如果 int 和 double 是局部方法变量,则在堆栈中分配;如果是成员变量,则在堆中分配
变量。在方法中,当调用方法时,局部变量被推入堆栈
当方法调用完成时,堆栈指针会递减。在多线程应用程序中,每个线程
将拥有自己的堆栈,但共享相同的堆。这就是为什么在代码中应该小心以避免任何
堆空间中的并发访问问题。堆栈是线程安全的(每个线程都有自己的堆栈),但是
除非通过代码进行同步保护,否则堆不是线程安全的。
此链接也很有用 http://www.programmerinterview.com/index.php/data-structs/difference- Between-stack-and-heap/
Each time an object is created in it goes into the area of memory known as heap. The primitive variables like
int and double are allocated in the stack, if they are local method variables and in the heap if they are member
variables . In methods local variables are pushed into stack when a method is invoked
and stack pointer is decremented when a method call is completed. In a multithreaded application each thread
will have its own stack but will share the same heap. This is why care should be taken in your code to avoid any
concurrent access issues in the heap space. The stack is threadsafe (each thread will have its own stack) but the
heap is not thread safe unless guarded with synchronisation through your code.
This link is also useful http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/
m 是对 MyClass 对象的引用,因此 m 存储在主线程的堆栈中,但 MyClass 的对象存储在堆中。因此 myInt 和 myString 存储在堆中。
请注意,m 只是一个引用(内存地址)并且位于主堆栈上。当 m 释放时,GC 从堆中清除 MyClass 对象
有关更多详细信息,请阅读本文的所有四个部分
https://www .c-sharpcorner.com/article/C-Sharp-heaping-vs-stacking-in-net-part-i/
m is a reference to an object of MyClass so m is stores in the stack of main thread but the object of MyClass stores in the heap. Therefore myInt and myString store in the heap.
Note that m is only a reference (an address to memory) and is on main stack. when m deallocated then GC clear the MyClass object from the heap
For more detail read all four parts of this article
https://www.c-sharpcorner.com/article/C-Sharp-heaping-vs-stacking-in-net-part-i/
根据标准定义(大家都这么说),所有值类型都将分配到堆栈上,而引用类型将分配到堆中。
这是错误的。仅本地(在函数上下文中)值类型/值类型数组在堆栈上分配。其他所有内容都分配在堆上。
As per the standard definition (things which everybody says), all Value Types will get allocated onto a Stack and Reference Types will go into the Heap.
This is wrong. Only local (in the context of a function) value types/arrays of value types are allocated on the stack. Everything else is allocated on the heap.
您应该将对象在哪里分配的问题作为实现细节来考虑。对于您来说,对象的位的确切存储位置并不重要。对象是引用类型还是值类型可能很重要,但在开始优化垃圾收集行为之前,您不必担心它将存储在哪里。
虽然在当前实现中引用类型始终分配在堆上,但值类型可能分配在堆栈上 - 但不一定。仅当值类型是未装箱的非转义本地或临时变量且未包含在引用类型中且未在寄存器中分配时,才会在堆栈上分配值类型。
有什么我错过的吗?
当然,如果我没有链接到 Eric Lippert 关于该主题的帖子,那就是我的失职:
You should consider the question of where objects get allocated as an implementation detail. It does not matter to you exactly where the bits of an object are stored. It may matter whether an object is a reference type or a value type, but you don't have to worry about where it will be stored until you start having to optimize garbage collection behavior.
While reference types are always allocated on the heap in current implementations, value types may be allocated on the stack -- but aren't necessarily. A value type is only allocated on the stack when it is an unboxed non-escaping local or temporary variable that is not contained within a reference type and not allocated in a register.
Is there anything I missed?
Of course, I would be remiss if I didn't link to Eric Lippert's posts on the topic:
m
在堆上分配,其中包括myInt
。在堆栈上分配基元类型(和结构)的情况是在方法调用期间,这会为堆栈上的局部变量分配空间(因为它更快)。例如:rv
、x
、y
都会在堆栈上。myInt
位于堆上的某个位置(并且必须通过this
指针访问)。m
is allocated on the heap, and that includesmyInt
. The situations where primitive types (and structs) are allocated on the stack is during method invocation, which allocates room for local variables on the stack (because it's faster). For example:rv
,x
,y
will all be on the stack.myInt
is somewhere on the heap (and must be access via thethis
pointer).“所有 VALUE 类型都将分配到堆栈”是非常非常错误的;结构变量可以作为方法变量存在于堆栈中。但是,类型上的字段与该类型一起存在。如果字段的声明类型是类,则值作为该对象的一部分位于堆上。如果字段的声明类型是结构体,则无论该结构体存在于何处,这些字段都是该结构体的一部分。
即使方法变量也可以位于堆上,如果它们被捕获(lambda/匿名方法),或者是(例如)迭代器块的一部分。
"All VALUE Types will get allocated to Stack" is very, very wrong; struct variables can live on the stack, as method variables. However, fields on a type live with that type. If a field's declaring type is a class, the values are on the heap as part of that object. If a field's declaring type is a struct, the fields are part of that struct where-ever that struct lives.
Even method variables can be on the heap, if they are captured (lambda/anon-method), or part of (for example) an iterator block.
很好的解释:
第 1 部分:http://www.c-sharpcorner .com/uploadfile/rmcochran/csharp_memory01122006130034pm/csharp_memory.aspx
第 2 部分:http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx
第 3 部分:http: //www.c-sharpcorner.com/UploadFile/rmcochran/chsarp_memory401152006094206AM/chsarp_memory4.aspx
第 4 部分:http://www.c-sharpcorner.com/uploadfile/rmcochran/csharp_memory_401282006141834pm/csharp_memory_4.aspx
Excellent explanation:
Part1: http://www.c-sharpcorner.com/uploadfile/rmcochran/csharp_memory01122006130034pm/csharp_memory.aspx
Part 2: http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory2B01142006125918PM/csharp_memory2B.aspx
Part 3: http://www.c-sharpcorner.com/UploadFile/rmcochran/chsarp_memory401152006094206AM/chsarp_memory4.aspx
Part 4: http://www.c-sharpcorner.com/uploadfile/rmcochran/csharp_memory_401282006141834pm/csharp_memory_4.aspx
堆
考虑以下方法:
该方法是递归的,这意味着它调用自身。 每次进入方法时,都会在堆栈上分配一个新的 int,每次方法退出时,都会释放 int。
堆
考虑以下方法:
在上面的示例中,我们首先创建一个由变量 ref1 引用的 StringBuilder 对象,然后写出其内容。然后,该 StringBuilder 对象立即符合垃圾回收条件,因为随后没有任何东西使用它。然后,我们创建另一个由变量 ref2 引用的 StringBuilder,并将该引用复制到 ref3。即使在那之后不再使用 ref2,ref3 也会使相同的 StringBuilder 对象保持活动状态 - 确保在我们使用完 ref3 之前它不会变得符合收集条件。
Stack
Consider the following method:
This method is recursive, meaning that it calls itself. Each time the method is entered, a new int is allocated on the stack, and each time the method exits, the int is deallocated.
Heap
Consider the following method:
In the above example, we start by creating a StringBuilder object referenced by the variable ref1, and then write out its content. That StringBuilder object is then immediately eligible for garbage collection, because nothing subsequently uses it. Then, we create another StringBuilder referenced by variable ref2, and copy that reference to ref3. Even though ref2 is not used after that point, ref3 keeps the same StringBuilder object alive—ensuring that it doesn’t become eligible for collection until we’ve finished using ref3.
简单的措施
值类型可以在堆栈上进行扩展,它是可以分配给某些未来主义数据结构的实现细节。
因此,最好了解值和引用类型的工作原理,值类型将按值复制,这意味着当您将值类型作为参数传递给 FUNCTION 时,它会自然复制,这意味着您将拥有一个全新的副本。
引用类型是通过引用传递的(同样不要考虑引用会在未来的版本中再次存储地址,它可能存储在其他一些数据结构上。)
所以在你的情况下
myInt 是一个 int ,它被封装在一个类中,该类当然是一个引用类型,因此它将与存储在“THE HEAP”中的类的实例绑定。
我建议,您可以开始阅读 ERIC LIPPERTS 撰写的博客。
Eric 的博客 < /a>
simple measures
Value type can be stred on THE STACK ,it is the implementaional detail it can be allocated to the some futuristist data structure.
so, it is better to understand how value and reference type works , Value type will be copied by value that means when you pass a value type as a param to a FUNCTION than it will be copied by nature means you will have a total new copy.
Reference types are passed by reference ( againg do not consider reference will store a address again in some future versions ,it may be stored on some other data structures.)
so in your case
myInt is a int which is ecapsulated in a class which offcourse an reference type so it will be tied to the instance of the class which will be stored on 'THE HEAP'.
i would suggest , you can start reading blogs written by ERIC LIPPERTS.
Eric's Blog