views:

167

answers:

4

I saw a question yesterday which raised (for me) another question. Please look at the following code:

public class Class1
{
   int A; //as I uderstand, int is value type and therefore lives in the stack
}

class Class2
{
    Run()
   {
       Class1 instance1 = new Class1();
       instance1.A = 10;  //it points to value type, but isnt this reference (on heap)?
   }
}

Or while creating the instance of Class1, its field types are created on the heap as well? But then I do not understand when it would really be on the stack as almost always you need to create an instance of object in order to use it fields.

+1  A: 

Local struct (value type) variables are stored on the stack, value type fields of a class are stored on the heap.

Andrew Bezzub
Unless (1) the local varaible is the closed-over outer local of an anonymous method or lambda expression, or (2) the local is in an iterator block, or (3) the jitter decides to use registers instead of the stack.
Eric Lippert
+1  A: 

Ok int is a value type but '1' (what an awful name for a class) is a reference type. This means that any instance of '1' is on the heap.

Preet Sangha
+7  A: 

First off, it's an implementation detail of Microsoft's CLR. Other specifications are not guaranteed to follow the same behavior, nor are further releases from Microsoft.

But yes, fields of a class are stored on the managed heap along with the class.

See this recent question for a longer explanation from Eric Lippert. http://stackoverflow.com/questions/2559271/stack-heap-understanding-question/2561622#2561622

Anthony Pegram
It is not a compiler implementation detail. Storage and layout of class objects is determined by the CLR. Its behavior is well defined by Ecma-335.
Hans Passant
Yes, I misspoke. Corrected.
Anthony Pegram
@nobugz: indeed, default layout is well-described. Also, the CLI spec says that *logically* there is an array of locals and temporaries (plus a local pool) associated with each method, that is not on the GC heap. Nowhere does it say that this logical array must be implemented by changing the value of the esp register to keep the locals on "the stack", whatever that is. The details of whether locals actually go on "the stack" or "the heap" is an implementation detail of the runtime. As long as the implementation behaves according to the specification, you can store stuff anywhere you want.
Eric Lippert
+3  A: 

as I understand, int is value type and therefore lives in the stack

Your understanding is incorrect. Value types are called "value types" because they are copied by value. Reference types are called "reference types" because they are copied by reference. It is not at all true that "value types always live on the stack". If that were true, they would be called "stack types" and "heap types".

The truth is that this is an implementation detail. Different framework implementations can choose to use the stack and the heap as they like. Here's how the Microsoft implementation does it:

  • the value of a variable of reference type is a reference to heap memory. A reference is basically a 32 bit or 64 bit integer.
  • the value of a variable of value type is its value.
  • the values of local variables are stored on the stack unless the local variables are in an iterator block or are closed-over outer variables of an anonymous method or a lambda expression. In those cases the values of local variables are stored on the heap. Unless of course the local variables can be optimized away, in which case there is no storage at all. Or perhaps they can be enregistered, in which case they are neither on the stack nor the heap, they are in processor registers.
  • the values of instance variables of reference types and static variables are stored on the heap.

Is that clear?

it points to value type, but isn't this reference (on heap)?

The field "A" is of value type. It is a field, and therefore that variable is stored on the heap.

while creating the instance of Class1, its field types are created on the heap as well?

The storage for the instance variables is on the heap, yes.

But then I do not understand when it would really be on the stack as almost always you need to create an instance of object in order to use it fields.

It would never be on the stack. As I said above, the only things that go on the stack are local variables (and compiler-generated temporaries) that are not closed-over locals of a lambda or anonymous method and are not in an iterator block. And of course, the jitter is free to keep them off the stack entirely and put them in registers if there are free registers.

But really, I have to ask, why do you care what goes on the stack and what goes on the heap? What goes on the stack is stuff we can cheaply put on the stack; everything else goes on the heap.

Eric Lippert
I have got the book from John Sharp stating that "Value types are created on the stack while reference types on the heap". Do not understand it, too.
Tomas
"the values of instance and static variables are stored on the heap." Except for struct-typed instance variables of an instance that has been stored on the stack, right?
Joren