2

In an application one should always try their best to ensure code is fully tested, and is written in such a way that malformed input or actions are handled gracefully.

We are only human though and mistakes creep in, in a last ditch effort to improve the user-experience instead of unceremoniously crashing to the desktop it is common to catch unhanded exceptions, throw a message to the user and record some fault information.

Usually a PDB is not distributed with the finished program and as such a system trace will not contain line numbers which can make it difficult to locate the offending line that threw the error.

Take the following example program (a .net console app for simplicity)

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

If that gets run without .pdb file present it will dutifully catch the error and report on it.

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

Is there any way to include the point in user code at which the fault occured or is this simply not present in the executable (obviously some symbol information is included as we can see the DoStuff function name.

For example is there any way I could log int value = data[parameter]; in addition to the stack trace.

Hugoagogo
  • 1,598
  • 16
  • 34
  • The way to get this information is precisely with the pdb files. About including the line of code, it no longer exists on the compiled executable, unless you ship the source code too. – Alejandro Jul 16 '21 at 02:48
  • I suppose from this direction, what symbol information is included in the executable as the function names clearly make it in. Is there any way to include the symbols in the exe without a pdb. – Hugoagogo Jul 16 '21 at 02:54

1 Answers1

3

What you see in this call stack without PDBs is available because your C# code is provided as Intermediate Language (IL).

Think like this: everything you could do via reflection (e.g. asking for classes and asking classes for their methods) is also available in the IL code and thus can be part of the stack trace.

But still, the IL code is optimized in a release build and e.g. unused variables can be removed.

Is there any way to include the point

No. That information is in the PDBs. The idea is that you build the PDBs even for a release build and store them in a symbol server at least for the versions that you ship to customers.

I would also not just catch an exception and show information to the user or save it in a log file. Instead, create a crash dump file (.DMP) that you can analyze on your PC using the PDBs you have stored for exactly that purpose.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • This is a good answer, thankyou for the links, would you have any reccomended refferences on generating a dump file automatically when an unhandled exception occurs. – Hugoagogo Jul 16 '21 at 05:21
  • For anybody else looking I found https://brakertech.com/howto-c-generate-dump-file-on-crash/ which seems to work for generating minidumps without having touch the registry. – Hugoagogo Jul 16 '21 at 06:03
  • @Hugoagogo: this will work for most cases (80%+ in my experience), except the most severe ones. Assume you have a buffer overflow which destroys the code you expect to take the crash dump. In such a case you're unlucky. If the OS does it from outside (like LocalDumps Registry Keys), it will still work. – Thomas Weller Jul 16 '21 at 06:55
  • 1
    Understood, for our application catching 80% of the errors with 10% of effort is acceptable. – Hugoagogo Jul 16 '21 at 07:32