0

I am struggeling with a weird NullReferenceException which occurs when I try to compare an attribute of a type derived from a Matrix type from the MathNet library to nullptr.

I want to write a a C++/CLI Class Library with a class Transformation, derived from MathNet::Numerics::LinearAlgebra::Matrix, which should represent Positions in 3D Space as a 4x4 Matrix in homogeneous coordinates. Because I want to be able to set positions relative to other positions i have an attribute Transformation^ parent. By if(parent == nullptr){ ... } I want to test, if the current Transformation has a parent, but I get this Exception in the line with if(parent == nullptr):

An unhandled exception of type 'System.NullReferenceException' occurred in MathNet.Iridium.dll 
Additional information: Object reference not set to an instance of an object.

My Transformation class looks like this:

/// Transformation.h
using namespace MathNet::Numerics::LinearAlgebra;
using namespace System;
ref class Transformation : Matrix
//ref class Transformation : A
{
public:
    Transformation(void);
    Transformation^ parent;
    void DoSomething();
};


/// Transformation.cpp
#include "StdAfx.h"
#include "Transformation.h"
Transformation::Transformation(void) : Matrix(4,4)
{
}
void Transformation::DoSomething()
{
    if(parent == nullptr)   // Produces NullReferenceException
    {
        Console::WriteLine("parent is nullptr");
    }
    Matrix^ m;
    if(m == nullptr)        // Produces NullReferenceException, too
    {
        Console::WriteLine("m is nullptr");
    }
}

Comparing any variable of Matrix type, that is actually null, to nullptr seems to throw this Exception. If it is initialized properly there is no Exception, so this works fine:

Matrix^ m = gcnew Matrix(4,4);
if(m == nullptr)        // works fine
{
    Console::WriteLine("");
}

When derive Transformation from a different class, ref class Transformation : A instead of ref class Transformation : Matrix, everything works fine, too.

And now it gets really weird. I wanted to use my class library in a C#-Application. Calling t.DoSomething() on a Transformation t throws the NullReferenceException. BUT, if I include the null-test directly in my C# Application, it works:

Transformation t = new Transformation();
// t.DoSomething();      // Throws NullReferenceException
if (t.parent == null)    // OK!
{
    Console.WriteLine("parent is null");
}

Doing the same in a C++/ClI application again throws the NullReferenceException:

Transformation^ t = gcnew Transformation();
// t->DoSomething();     // Throws NullReferenceException
if(t->parent == nullptr) // Throws NullReferenceException
{
    Console::WriteLine("parent is nullptr");
}

Any suggestions where this might come from? I am really quite puzzled...

I use the MathNet.Idirium Library, Version 2008.8.16.470

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
richn
  • 164
  • 2
  • 9
  • This normally indicates that *this* is null. Doesn't match your test code though. Maybe a versioning problem. – Hans Passant Oct 20 '11 at 12:11
  • If this (meaning t in this context) were null, I couldn't call DoSomething() on t or am I wrong? The Exception is thrown only inside DoSomething(), not when it is called. – richn Oct 20 '11 at 12:27
  • It is different for C++/CLI, it doesn't generate code to ensure that *this* is not null like C# does. It bombs later when you try to access a class member. Can be hard to diagnose. But I agree that your tests make it very unlikely that this is the real cause of the problem. Look at *this* in the debugger for any kind of hint. – Hans Passant Oct 20 '11 at 12:33
  • I can inspect "this" in the Debugger (doesn't point to "") and also its nested attribute of type Matrix has been initialized correctly. Only parent points to "". Because the problem also occurs with local variables (see class definition above, Matrix^ m) I guess it might not be a problem with "this"? – richn Oct 20 '11 at 12:42

1 Answers1

1

Its possible in C# at least for the == operator to be implemented in a way that throws a null reference.

Can you try calling Object::ReferenceEquals(obj, null) and see if that works or not?

Andy
  • 8,432
  • 6
  • 38
  • 76
  • Thank you Andy, comparing with `if(Object::ReferenceEquals(parent, nullptr))` passes without an Excception! So this is a subtlety in the implementation of Matrix? – richn Oct 20 '11 at 12:55
  • @richn : If by 'subtlety' you mean 'bug' then yes. – ildjarn Oct 20 '11 at 13:16
  • @ildjarn Haha ;-) I just wanted to know if I could "see" when to use `ReferenceEquals()` and when `==`. – richn Oct 20 '11 at 13:31
  • @richn: The only way to "see" would be if you can look at the source code for Matrix and look at the operator== implementation. So if you don't have it and can't decompile it, you maybe out of luck. Its most certainly a bug in that code though, as Equals, GetHashCode and operator implemenations must NEVER throw exceptions, according to MSDN documentation. – Andy Oct 20 '11 at 14:58
  • @Andy MathNet is open source, and after a quick look into the implementation of Matrix I couldn't find any implementation of the == operator. But never mind, I will go with your fix for now and search for the reason why `==` doens't work when I have more time. Thanks a lot for your help! – richn Oct 21 '11 at 07:45
  • @richn I'm not sure then. I know C#, I must admit that managed C++ isn't something I've worked with. I assumed if == wasn't defined for that type you'd get a compile error, but apparently not! – Andy Oct 22 '11 at 00:48