views:

2591

answers:

4

From a SO answer about Heap and Stack, it raised me a question: Why it is important to know where the variables are allocated?

At another answer someone pointed that the stack is faster. Is this the only implication? Could someone give a code example where a simple allocation location change could solve a problem (eg. performance)?

Note that this question is .NET specific

+3  A: 

I think the simplest reason is that if it is in the Heap the the garbage collection needs to deal with the variable once it is no longer needed. When on a Stack, the variable is dismissed with whatever was using it, such as a method that instantiated it.

DavGarcia
+5  A: 

(edit: My original answer contained the oversimplification "structs are allocated on the stack" and confused stack-vs-heap and value-vs-reference concerns a bit, because they are coupled in C#.)

Whether objects live on the stack or not is an implementation detail which is not very important. Jon has already explained this well. When choosing between using a class and struct, it is more important to realize that reference types work differently than value types. Take the following simple class as an example:

public class Foo
{
   public int X = 0;
}

Now consider the following code:

Foo foo = new Foo();
Foo foo2 = foo;
foo2.X = 1;

In this example, foo and foo2 are references to the same object. Setting X on foo2 will also affect foo1. If we change the Foo class to a struct then this is no longer the case. This is because structs are not accessed through references. Assigning foo2 will actually make a copy.

One of the reasons for putting stuff on the stack is that the garbage collector does not have to clean it up. You typically should not worry about such things; just use classes! Modern garbage collectors do a pretty good job. Some modern virtual machines (like java 1.6) can even determine whether it is safe to allocate objects on the stack even if they are not value types.

Wim Coenen
While your example and explanation are correct, you've demonstrated a counterexample to your first sentence. What is "Foo.X"? An int, which is a value type - and yet it always lives on the heap. The claim of "classes are heap allocated, structs are stack allocated" is an oversimplification.
Jon Skeet
A better wording would be to say that value types are allocated where they're declared. If they're declared as local variables in a function, they're on the stack. If they're declared as members in a class, they're on the heap, as part of that class.
jalf
I will not vote up this answer because it mixes reference vs value implications with heap vs stack implications.
Jader Dias
Thanks for the correction, it has triggered an "Aha!" moment. I now realize that stack-vs-heap is a relatively unimportant implementation detail in C#, and that value-vs-reference is the real issue here. I should have explained it that way.
Wim Coenen
now I voted up because of your corrections
Jader Dias
Someone might correct me on this, but aren't class members/properties also stored on the heap? e.g. person.Age = 30; is on the heap
Chris S
@chris: Yes, that's what Jon is saying in the first comment, and why I added a note "look at the comments". What's the best practice here, should I go in and fix the post proper instead of referring to the comments?
Wim Coenen
I went ahead and fixed it proper since people appear to skip over the "look at the comments" note.
Wim Coenen
+4  A: 

So long as you know what the semantics are, the only consequences of stack vs heap are in terms of making sure you don't overflow the stack, and being aware that there's a cost associated with garbage collecting the heap.

For instance, the JIT could notice that a newly created object was never used outside the current method (the reference could never escape elsewhere) and allocate it on the stack. It doesn't do that at the moment, but it would be a legal thing to do.

Likewise the C# compiler could decide to allocate all local variables on the heap - the stack would just contain a reference to an instance of MyMethodLocalVariables and all variable access would be implemented via that. (In fact, variables captured by delegates or iterator blocks already have this sort of behaviour.)

Your question came up while Eric Lippert was reviewing C# in Depth - I have a section explaining what goes where in C# 1, and he reckoned that developers shouldn't care.

Jon Skeet
Eric is the man. You are lucky to have such a good reviewer.
RichardOD
+2  A: 

In .NET there's little to discuss as it is not the user of a type who decides where to allocate instances.

Reference types are always allocated on the heap. Value types are per default allocated on the stack. The exception is if the value type is part of a reference type in which case it is allocated on the heap along with the reference type. I.e. the designer of a type makes this decision on behalf of the users.

In languages such as C or C++ the user can decide where data is allocated and for some special cases it may be significantly faster to allocate from the stack compared to allocating from the heap.

This has to do with how heap allocations are handled for C / C++. In fact heap allocation is pretty fast in .NET (except when it triggers a garbage collect), so even if you could decide where to allocate, my guess is that the difference would not be significant.

However, since the heap is garbage collected and the stack is not, obviously you would see some differences in certain cases, but it is hardly relevant given the fact that you don't really have a choice in .NET.

Brian Rasmussen