Reputation: 9396
Consider the following statements
void foo()
{
string text = "something";
int a = 10;
int b = a;
var array = new int[5]{2,1,3,5,4};
GC.Collect();
}
**Stack** **Heap**
text = 0x20 0x20 something
a = 10
b = 10
array = 0x50:0x55 0x50 2
0x52 1
0x53 3
0x54 5
0x55 4
Some assumptions:
The questions were:
What is the value in the Heap ?
I answered the memory locations 0x20, 0x50-0x55 will be reclaimed and deleted. Again he asked, what values does the memory locations have? I guessed may be garbage values. He said incorrect. (WTx?)
What happens to the items in the stack ? What values does text, a, b, array hold ?
I answered that since the references that they contain are already deleted and they will also be reclaimed. He asked what values does the variables hold now.
Redraw the above tabular column after GC Collection.
After GC runs
**Stack** **Heap**
text (cleared) 0x20 Garbage/NULL
a (cleared)
b (cleared)
array (cleared) 0x50 Garbage/NULL
0x52 Garbage/NULL
0x53 Garbage/NULL
0x54 Garbage/NULL
0x55 Garbage/NULL
Result: He said that answers were incorrect. Any ideas what was I missing here ?
Upvotes: 1
Views: 212
Reputation: 941505
One of three possible things can happen to the memory formerly occupied by the object:
The Large Object Heap is a bit different, the first bullet won't apply. Do note that the mental model of "memory locations are deleted" is not very accurate. You'll be much ahead with "memory locations will be re-used". Much the same applies to the stack, there is no active "delete the stack frame" code. It is simply forgotten and will get overwritten sooner or later. Almost always sooner, microseconds.
Upvotes: 2
Reputation: 391336
It is impossible to give a deterministic answer to this, but some thought to the behavior can be given.
First of all, all the variables are local variables. As such, after the method has returned, those variables are out of scope. The exact place in memory (or in CPU registers) where they lived now contains unknown content. Other things may be living in that memory area now, we don't know. We cannot know. As such, are they cleared? Who knows.
However, for all intents and purposes, those variables no longer exist after the method has returned.
If you think "these variables live on the stack", please note that the stack is an implementation detail.
Now, additionally you allocated two heap objects, a string and an array.
Since these were only referenced by local variables, which are out of scope after the method has returned, these are no longer considered live and is eligible for collection.
However, what does "collection" here mean? Does it mean that the garbage collector clears the memory area? Not at all.
Instead, when the garbage collects memory, it actually does the opposite, it collects living objects. These objects are compacted in memory and moved around, and the area where that string and that array lived can be overwritten by other objects. Could be an array containing only zeroes, in which case the memory area will likely look "cleared", but probably not.
But hang on, that string, something special happens to it. Since the string was written in source code as a literal it is actually interned when the program starts. As such, it is not collected, it will still live somewhere in memory. In other words, that string is still alive and well, somewhere in memory. Could be the same place it was in when the variable referred to it, could be somewhere else. We cannot know.
The bytes making up the array object, however, can be overwritten by the garbage collector when it compacts live objects.
OK, so all this happens after the method returned.
What happens if GC.Collect()
runs a garbage collection cycle before the method returns?
Well, if you're in a RELEASE build, everything above still holds. The fact that you have a local variable in a method referring to something on the heap means nothing if the variable is no longer used in the method (ie. you've passed the last usage in the execution timeline).
However, if you're in a DEBUG build, or have a debugger attached, all local variables scope are prolonged to the end of the method. As such, they're still considered live references and will keep the objects on the heap alive as well. In this case the array will not be collected.
However, any time garbage collection runs, the address of where heap objects live in memory may change, since the objects were compacted together with other objects or promoted to a different generation.
Here comes the actual answer to your question:
Much of the above is implementation details. Things we're not supposed to care about because it may change due to optimizations.
There's a lot of things we can reason about but how the actual underlying memory is handled we shouldn't.
You said in your comment that you thought you were in a compiler writer interview and I would say that feeling is correct. If you were to interview for the JIT or memory management team at Microsoft, some knowledge about how these things work will at the very least be taught as part of the job, but may be a bonus if you already know.
However, for a normal .NET programmer, this is unnecessary to care about. Other smart people care about this.
Upvotes: 5
Reputation: 27944
This is something you can not answer because it is a implementation detail of you execution platform. Depending on the platform/ version the answer can be totally different. What you can consider is the method scope, value type vs reference type and that strings are special.
Upvotes: 1