当引发异常时返回堆栈跟踪时,C# 尾递归优化如何实现

发布于 2024-09-28 05:33:16 字数 114 浏览 4 评论 0原文

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

很酷又爱笑 2024-10-05 05:33:16

好吧,只有当您希望获得准确的堆栈跟踪时才重要:)

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

这是一个非常简单的例子来说明这个问题:

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)

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文