Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does .net managed memory handle value types inside objects?

Tags:

.net

memory

public class MyClass
{
    public int Age;
    public int ID;
}

public void MyMethod() 
{
    MyClass m = new MyClass();
    int newID;
}

To my understanding, the following is true:

  1. The reference m lives on the stack and goes out of scope when MyMethod() exits.
  2. The value type newID lives on the stack and goes out of scope when MyMethod() exits.
  3. The object created by the new operator lives in the heap and becomes reclaimable by the GC when MyMethod() exits, assuming no other reference to the object exists.

Here is my question:

  1. Do value types within objects live on the stack or the heap?
  2. Is boxing/unboxing value types in an object a concern?
  3. Are there any detailed, yet understandable, resources on this topic?

Logically, I'd think value types inside classes would be in the heap, but I'm not sure if they have to be boxed to get there.

Edit:

Suggested reading for this topic:

  1. CLR Via C# by Jeffrey Richter
  2. Essential .NET by Don Box
like image 330
Ben Robbins Avatar asked Aug 24 '08 03:08

Ben Robbins


People also ask

Where value types are stored in memory?

Two Parts of Memory In short, value types are stored in the Stack and reference types are stored in the Heap.

Where are C# value types stored in the memory?

While value types are stored generally in the stack, reference types are stored in the managed heap. A value type derives from System. ValueType and contains the data inside its own memory allocation.

How are C# objects stored in memory?

In C# there are two places where an object can be stored -- the heap and the stack. Objects allocated on the stack are available only inside of a stack frame (execution of a method), while objects allocated on the heap can be accessed from anywhere.

Why value types are stored in stack?

A value type stores its contents in memory allocated in the stack, so we can say value types are allocated in the stack in Swift. ? The misconception is that most people think value types are always stored in the Stack. Value types can be stored inside the stack when they are either temporary or local variables.


1 Answers

Value-type values for a class have to live together with the object instance in the managed heap. The thread's stack for a method only lives for the duration of a method; how can the value persist if it only exists within that stack?

A class' object size in the managed heap is the sum of its value-type fields, reference-type pointers, and additional CLR overhead variables like the Sync block index. When one assigns a value to an object's value-type field, the CLR copies the value to the space allocated within the object for that particluar field.

Take for example, a simple class with a single field.

public class EmbeddedValues
{
  public int NumberField;
}

And with it, a simple testing class.

public class EmbeddedTest
{
  public void TestEmbeddedValues()
  {
    EmbeddedValues valueContainer = new EmbeddedValues();

    valueContainer.NumberField = 20;
    int publicField = valueContainer.NumberField;
  }
}

If you use the MSIL Disassembler provided by the .NET Framework SDK to peek at the IL code for EmbeddedTest.TestEmbeddedValues()

.method public hidebysig instance void  TestEmbeddedValues() cil managed
{
  // Code size       23 (0x17)
  .maxstack  2
  .locals init ([0] class soapextensions.EmbeddedValues valueContainer,
           [1] int32 publicField)
  IL_0000:  nop
  IL_0001:  newobj     instance void soapextensions.EmbeddedValues::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldc.i4.s   20
  IL_000a:  stfld      int32 soapextensions.EmbeddedValues::NumberField
  IL_000f:  ldloc.0
  IL_0010:  ldfld      int32 soapextensions.EmbeddedValues::NumberField
  IL_0015:  stloc.1
  IL_0016:  ret
} // end of method EmbeddedTest::TestEmbeddedValues

Notice the CLR is being told to stfld the loaded value of "20" in the stack to the loaded EmbeddValues' NumberField field location, directly into the managed heap. Similarly, when retrieving the value, it uses ldfld instruction to directly copy the value out of that managed heap location into the thread stack. No box/unboxing happens with these types of operations.

like image 176
icelava Avatar answered Sep 28 '22 08:09

icelava