Fabulous Adventures In Coding
Eric Lippert is a principal developer on the C# compiler team. Learn more about Eric.
As you know if you've read this blog for a while, I'm disturbed by the myth that "value types go on the stack". Unfortunately, there are plenty of examples in our own documentation and in many books that reinforce this myth, either subtly or overtly. I'm opposed to it because:
The way in the past I've usually pushed back on this myth is to say that the real statement should be "in the Microsoft implementation of C# on the desktop CLR, value types are stored on the stack when the value is a local variable or temporary that is not a closed-over local variable of a lambda or anonymous method, and the method body is not an iterator block, and the jitter chooses to not enregister the value."
The sheer number of weasel words in there is astounding, but they're all necessary:
Having made these points many times in the last few years, I've realized that the fundamental problem is in the mistaken belief that the type system has anything whatsoever to do with the storage allocation strategy. It is simply false that the choice of whether to use the stack or the heap has anything fundamentally to do with the type of the thing being stored. The truth is: the choice of allocation mechanism has to do only with the known required lifetime of the storage.
Once you look at it that way then everything suddenly starts making much more sense. Let's break it down into some simple declarative sentences.
Now we come to implementation details. In the Microsoft implementation of C# on the CLR:
And now things follow very naturally:
Once you abandon entirely the crazy idea that the type of a value has anything whatsoever to do with the storage, it becomes much easier to reason about it. Of course, my point above stands: you don't need to reason about it unless you are writing unsafe code or doing some sort of heavy interoperating with unmanaged code. Let the compiler and the runtime manage the lifetime of your storage locations; that's what its good at.
Off topic, but I find these things "in the Microsoft implementation of C# on the desktop CLR, value types are stored on the stack when the value is a local variable or temporary that is not a closed-over local variable of a lambda or anonymous method, and the method body is not an iterator block, and the jitter chooses to not enregister the value", much easier to understand if I imagine Anders saying them.
Isn't the title a bit melodramatic... Sounds like a 1950's black and white
Very good post.
I think that we should always use "Thread Stack" instead of "stack" in sentences. It will be helpful for the beginers.
Knowing I am working on an 8 way Xeon this discussion seems rather silly. There are about 8000 registers, 256 memory indexers, 64 scoreboards, 128MB of various cache.
Per Intel 98% of things loaded in registers are never used (mostly predictive branching).
This means the stack and heap are at about 400 place for every clock cycle (assuming you could acually keep the processors loaded).
Hiding this mess from the user is a real fine idea.
Of course now you need to add async method to your list of weasle words.
One (and only) of the best truths that I have ever enjoyed reading !!
Excellent article. Thank you!