0

I have a very strange case where I have a null parameter in my class that I attempt to access (and hence cause a NullReferenceException which is expected) however the debugger reports a field from another entirely unrelated class is null instead. I have tried to reproduce this however I cannot. Can anyone explain what is going on?

I have made a new small test project with the same classes.

namespace WpfApp6
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Test_Click(object sender, RoutedEventArgs e)
        {
            var container = new SegmentedBinaryData();
            var temp = container.StringData[0x123,10];
        }
    }

    public class SegmentedBinaryData
    {
        public StringData StringData;
    }

    public class StringData
    {
        public string this[int address, int maxLength]
        {
            get => "lol";
            set { }
        }
    }
}

If you run this test project and press the Test button you get the following exception:

System.NullReferenceException: 'Object reference not set to an
instance of an object.' container.StringData was null.

This makes perfect sense. In my actual project I get the following exception:

System.NullReferenceException: 'Object reference not set to an
instance of an object.' container.<SmoothXEnabled>k__BackingField was null.

SmoothXEnabled is a boolean property from another class that is not even in the same namespace not to mention it is not even referenced by this assembly in any way.

It should say "StringData" was null but it does not. Why is the VS2019 debugger getting confused here? I have tried debugging with VS2017 and I get the same error

I debugged the program in dnspy and it just says the generic "Object reference not set to an instance of an object." error instead which makes more sense and is what I expect the visual studio debugger to report.

SmoothXEnabled is defined in this class (from an entirely different assembly and DLL)

public abstract class ParameterViewModel : BaseViewModel, IDisposable
{
    public virtual bool SmoothTableEnabled { get; set; }
    public virtual bool SmoothEnabled { get; set; }
    public virtual bool SmoothXEnabled { get; set; }

If I continue to delete classes from the project eg I delete the class that contains SmoothXEnabled the debugger reports the following error instead:

System.NullReferenceException: 'Object reference not set to an
instance of an object.'container.CheckSumAddr was null.

CheckSumAddr is at least from the same namespace however it is also once again, not even instantiated or referenced from within the class that the NullReference is thrown. I can keep going through my program deleting classes and variables and the debugger reports a different random variable from a random class is null each time.

If I add a field to SegmentedBinaryData I can shift the "random" field that is named in the exception. It is almost like the debugger is accessing the "null" pointer, adding the offset (because of the indexer maybe?) then reaching another random variable?

Can anyone explain why the visual studio debugger is performing in this manner but the dnspy debugger is not?

edit: The reason this is important to resolve is the wrong field name being reported wasted a lot of time trying to track down how that could possibly be null. Had no field name been given I would have seen StringData was null and fixed the issue immediately. It was only after I debugged with dnspy did I realise that StringData was actually the problem.

rolls
  • 2,008
  • 4
  • 32
  • 50
  • Was the "actual project" compiled as a Release build? Also, when you say that it *says* which field was null, this is the new Exception details window inside the Debugger, right? This will sometimes get things wrong, unfortunately. – Lasse V. Karlsen Apr 23 '19 at 09:19
  • @Enigmativity how on earth is this a duplicate? I know what a nullreferenceexception is an how to fix it. I'm asking why does the compiler give the wrong field name. – rolls Apr 23 '19 at 09:27
  • @LasseVågsætherKarlsen it was compiled as debug. Correct this is the exception details window, but it is also the actual message inside the exception. – rolls Apr 23 '19 at 09:28
  • Is this Unity or Xamarin (both using Mono) by any chance? The NullReferenceException does not contain the field or variable name in .NET Framework or .NET Core. – Lasse V. Karlsen Apr 23 '19 at 09:43
  • 1
    Most likely the debugger is trying to figure out what specifically was null but it has to work backwards from the compiled code, and due to optimizations it gets it wrong. You're best (only?) recourse is to debug your application yourself and figure it out, and that hasn't changed. Optimizations is probably also why the debugger mentions the private field, as a property access can be optimized by inlining the code to access the field by the JITter, and if the debugger has to work backwards from JITted code, it *will* get it wrong sometimes. – Lasse V. Karlsen Apr 23 '19 at 09:46
  • 1
    In short, you shouldn't rely on this information but use it as a guide to initially focus your debugging efforts, but seeing as it can be wrong you should cast your net wider if you don't find the problem. – Lasse V. Karlsen Apr 23 '19 at 09:47
  • @LasseVågsætherKarlsen the issue here is it put me on a wild goose chase for hours trying to figure out why the named field was null and how it was even possible. Had it said nothing I would have just checked the StringData object and fixed the problem immediately. So the false/incorrect information wasted a lot of time. I did not have any optimisations enabeld either, everything was built in debug mode which confuses me further. It was .net 4.7.1 compiled for an x86 windows 10 platform. – rolls Apr 24 '19 at 02:51

0 Answers0