1

I had a .NET class which was not implementing IComparable interface. After I implemented IComparable interface on this class some c++ code using my class changed it's behavior unexpectedly. Now it throws a NullReferenceException

DWORD UnitsAdapter::GetUnitNames([Out]array<MyClass^>^% unitNames)
{

  ...

  unitNames = gcnew array<MyClass^>(10);

  DWORD dwRet = BUMC_OK;
  for (int i = 0; i < unitNames->Length; ++i)
  {
    unitNames[i] = nullptr;
    unitNames[i] = CoCliUnitsHelper::getUnitName(unitIds[i]);

    if (nullptr == unitNames[i])
      dwRet = BUMC_NOT_COMPLETE;
  }

  return dwRet;

}

The problem was in the line if (nullptr == unitNames[i]) which started using IComparable implementation to perform == operation!

The reason was a template from cliext utility header file.

//
// System::IComparable TEMPLATE COMPARISONS
//
template<typename _Value_t>
    bool operator==(System::IComparable<_Value_t>^ _Left,
        System::IComparable<_Value_t>^ _Right)
    {   // test if _Left == _Right
    return (_Left->CompareTo(_Right) == 0);
    }

Question 1: I am not a c++ expert, so can someone explain me why this implementation does not perform a null check on _Left before calling CompareTo() method ? According to MSDN Guidelines for Overloading Equals() and Operator == null checks must be done prior of doing anything inside == operator.

 ...
 // If both are null, or both are same instance, return true.
 if (System.Object.ReferenceEquals(a, b))
 {
        return true;
 }

 // If one is null, but not both, return false.
 if (((object)a == null) || ((object)b == null))
 {
        return false;
 }
 ...

Question 2: Is there probably some flaw in usage which leads to such an unpredictable behavior?

George Mamaladze
  • 7,593
  • 2
  • 36
  • 52
  • 1
    Not an answer, but holly crab, what I nightmare of a language... Microsoft knows how to mess things up, for sure. –  Nov 12 '12 at 15:27
  • The STL/CLR library is very problematic. It was two years late and suffers from severe perf problems. It is widely ignored, best you do the same. http://www.codeproject.com/Articles/24206/A-look-at-STL-CLR-performance-for-linear-container – Hans Passant Nov 12 '12 at 15:41

1 Answers1

2

so can someone explain me why this implementation does not perform a null check on _Left before calling CompareTo() method

Because whoever wrote it neglected to check for nulls.

Is there probably some flaw in usage which leads to such an unpredictable behavior?

Well, comparing a null pointer to something is probably an edge case, but I certainly wouldn't call it a "flaw". The implementation of == is incorrect.

To workaround this issue, you could reverse your equality check and/or check for null:

if (unitNames[i] == nullptr)
  dwRet = BUMC_NOT_COMPLETE;
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • The "WHOEVER" is [Microsoft STL/CLR](http://msdn.microsoft.com/en-us/library/bb385954.aspx) :) – George Mamaladze Nov 12 '12 at 15:41
  • 1
    The "WHOEVER" is the person (or people) at Microsoft that wrote the template(s). They're not infallible just because they work at MS. Feel free to file it as a bug with MS. – D Stanley Nov 12 '12 at 15:44