当抛出异常时返回堆栈跟踪信息的情况下,C#如何进行尾递归优化?

5

我看到一些关于C#中缺少尾递归优化的问题,据说这使得该语言不适合实现递归算法。然而,这引出了一个问题,我们如何进行尾递归优化,同时在抛出异常或使用反射检查调用堆栈并对其采取行动时仍能提供有意义的堆栈跟踪。

1个回答

6

如果您希望获得准确的堆栈跟踪,那么这很重要 :)

尾调用优化并不是唯一可能破坏堆栈跟踪的事情 - 最简单的例子就是内联,它肯定会影响到某些东西。基本上,任何依赖于准确堆栈跟踪的东西都是有风险的。

以下是一个非常简单的例子:

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();
    }
}

如果在不使用调试器的情况下构建和运行,则可能会出现以下情况:

at Program.Call3()
at Program.Main(String[] args)

基本上,要小心处理堆栈跟踪。


1
虽然我每天都要处理用户提交的错误信息,但即使有编译器优化,它们也有准确的堆栈跟踪。否则,我不确定我能完成多少任务 :-) - Carlo V. Dango
1
@Carlo:这可能是因为用户的堆栈跟踪路径中不包括内联或尾调用优化。此外,我强烈怀疑如果你仔细查看,偶尔会看到堆栈跟踪并不准确的情况,但只在你关心的帧中准确。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接