I'be seen a few questions regarding missing tail call optimization in C# supposedly making the language ill suited for recursive algorithm implementations. this, however,begs the question, how can we do tail call optimizations and still provide sensible stack traces when exceptions are raised or when reflection may be used to inspect the call stack and act upon it.
Well, it only matters if you expect to get an accurate stack trace :)
Tail-call optimizations aren't the only things that can destroy a stack trace - the simplest example is inlining, which can certainly affect things. Basically, anything which relies on the stack trace being accurate is taking a bit of a risk.
Here's a very simple example of exactly that problem:
using System;
using System.Runtime.CompilerServices;
class Program
{
static void Main(string[] args)
{
try
{
Call1();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
}
static void Call1()
{
Call2();
}
static void Call2()
{
Call3();
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void Call3()
{
Call4();
}
static void Call4()
{
Call5();
}
static void Call5()
{
throw new Exception();
}
}
Build and run without the debugger, and you may get this:
at Program.Call3()
at Program.Main(String[] args)
Basically, be careful what you do with stack traces.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With