When all optimizations are enabled, the JIT and GC cooperate so that local roots are relevant only as long as the local variable is still going to be used. This is a source of strange bugs—two of them are the Timer bug and the finalization race condition.
Why am I telling you all this? Well, it turns out there’s a cool SOS command called !GCInfo that can give you information on local root relevance within a method. In other words, it can tell you when (in terms of instructions) a local variable ceases to be an active local root.
For the sake of simplicity, let’s consider Debug builds only and the following method:
static void Main(string[] args)
{
string s = "Hello World";
Console.ReadLine();
}
Because of the Debug build, the local variable s is not going to be optimized away. Furthermore, its lifetime should extend until the end of the method, and not just the first line. Let’s verify this:
0:000> !CLRStack
OS Thread Id: 0x1f04 (0)
ESP EIP
[…edited for brevity…]
003ced00 704c9fbb System.IO.StreamReader.ReadBuffer()
003ced14 704c9e0c System.IO.StreamReader.ReadLine()
003ced34 70a5dd3d System.IO.TextReader+SyncTextReader.ReadLine()
003ced40 709a31c7 System.Console.ReadLine()
003ced48 005c009b FreakishTimerBug.Program.Main()
Read more: All Your Base Are Belong To Us