【问题标题】:More specific exception location in stacktrace without pdb file没有 pdb 文件的堆栈跟踪中更具体的异常位置
【发布时间】:2021-07-16 12:39:00
【问题描述】:

在应用程序中,应始终尽最大努力确保代码经过全面测试,并以能够优雅处理格式错误的输入或操作的方式编写。

尽管我们只是人类,错误会蔓延,为了改善用户体验而不是毫不客气地崩溃到桌面,这是很常见的,捕获未经处理的异常,向用户抛出消息并记录一些故障信息.

通常 PDB 不会与完成的程序一起分发,因此系统跟踪不会包含行号,这会导致难以找到引发错误的违规行。

采用以下示例程序(为简单起见,一个 .net 控制台应用程序)

using System;

namespace ExceptionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // Just in case we forget to catch something properly.
            System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;

            Console.WriteLine(DoStuff(10));

            Console.ReadKey();
        }

        static int DoStuff(int parameter)
        {
            int[] data = { 1, 2, 3, 4, 5, 6 };

            int value = data[parameter]; // Improperly checked code

            return value;
        }

        static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
        {
            Console.WriteLine(e.ExceptionObject.ToString());
            Console.WriteLine("Press Enter to continue");
            Console.ReadLine();
            Environment.Exit(1);
        }
    }
}

如果在没有 .pdb 文件的情况下运行,它将尽职尽责地捕获错误并报告它。

System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at ExceptionTest.Program.DoStuff(Int32 parameter)
   at ExceptionTest.Program.Main(String[] args)
Press Enter to continue

有没有办法在用户代码中包含错误发生的点,或者这根本不存在于可执行文件中(显然包含一些符号信息,因为我们可以看到 DoStuff 函数名称。

例如,除了堆栈跟踪之外,我还有什么方法可以记录 int value = data[parameter];

【问题讨论】:

  • 获取此信息的方法正是使用 pdb 文件。关于包含这行代码,它不再存在于编译的可执行文件中,除非你也发布了源代码。

标签: c# stack-trace unhandled-exception


【解决方案1】:

您在此调用堆栈中看到的没有 PDB 的内容是可用的,因为您的 C# 代码是作为中间语言 (IL) 提供的。

这样想:你可以通过反射做的所有事情(例如,请求类和请求类的方法)在 IL 代码中也可用,因此可以成为堆栈跟踪的一部分。

但是,IL 代码仍然在发布版本中进行了优化,例如可以删除未使用的变量。

有什么方法可以包含要点

没有。该信息在 PDB 中。这个想法是,您甚至可以为发布版本构建 PDB,store them in a symbol server 至少为您提供给客户的版本。

我也不会只是捕获异常并向用户显示信息或将其保存在日志文件中。取而代之的是 create a crash dump 文件 (.DMP),您可以使用您为此目的存储的 PDB 在您的 PC 上进行分析。

【讨论】:

  • 这是一个很好的答案,谢谢您的链接,您是否有任何关于在发生未处理的异常时自动生成转储文件的推荐参考。
  • 对于其他人,我发现brakertech.com/howto-c-generate-dump-file-on-crash 似乎可以在不接触注册表的情况下生成小型转储。
  • @Hugoagogo:这适用于大多数情况(根据我的经验,80% 以上),除了最严重的情况。假设您有一个缓冲区溢出,它破坏了您希望进行故障转储的代码。在这种情况下,你很不走运。如果操作系统从外部执行此操作(如 LocalDumps 注册表项),它仍然可以工作。
  • 明白,对于我们的应用程序来说,用 10% 的努力捕获 80% 的错误是可以接受的。
猜你喜欢
  • 2012-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-03
  • 2011-01-05
  • 2011-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多