NullReferenceException on exit from managed/unmanaged code.

A

andrew.bell.ia

Hi,

I'm trying to put together some managed and unmanaged code. Everything
works fine until the program exits, and I suppose the garbage collector
runs to finalize things. Then I get:

Unhandled Exception: System.NullReferenceException: Object reference
not set to
an instance of an object.
at std.list said:
.clear(list<int,std::allocator<int> >* )

at std.list said:
._Tidy(list<int,std::allocator<int> >* )

at Tab.MCell.Finalize()

I can't think why I would get a NullReferenceException in managed code.
Any ideas greatly appreciated.

The std::list is in unmanaged code:

#include <list>
#include <math.h>

using namespace std;

namespace Tab {

class __declspec(dllexport) Cell
{
private:
int _row;
int _col;
list<int> _vals;
...
};
}

The managed code looks like:

#using <mscorlib.dll>

#include "Cell.h"

using namespace std;
using namespace System::Collections;

namespace Tab {

public __gc class MCell
{
//
// DATA
//
private:
Cell __nogc *_cell;
//
// FUNCTIONS
//
public:
MCell(Cell *c)
{ _cell = c; }
MCell(int row, int col)
{ _cell = new Cell(row, col); }
~MCell()
{ _cell->~Cell(); }
....
};
}

The unmanaged code is built with the following which makes a DLL (the
8.3 directories are just where the stl stuff is on my machine):

cl -GX -I"C:\PROGRA~1\MIA4C6~1\include" Cell.cc /LD /link
/libpath:"C:\PROGRA~1\MIA4C6~1\lib"

The executable gets built with:

cl -GX -I"C:\PROGRA~1\MIA4C6~1\include" /clr CTest.cc /link
/libpath:"C:\PROGRA~1\MIA4C6~1\lib" Cell.lib

Thanks in advance!

-- Andrew Bell
(e-mail address removed)
 
T

Tamas Demjen

I'm trying to put together some managed and unmanaged code. Everything
works fine until the program exits, and I suppose the garbage collector
runs to finalize things. Then I get:

Unhandled Exception: System.NullReferenceException: Object reference
not set to
an instance of an object.
at std.list<int,std::allocator<int>
[...]
MCell(int row, int col)
{ _cell = new Cell(row, col); }
~MCell()
{ _cell->~Cell(); }

Is there a reason why you're calling the destructor explicitly? There's
only one case when you can (should) do it, and that's when the object is
created using the inplace new operator. So you either do

//A:
cell = new Cell(row, col);
[...]
delete cell;
cell = 0; // just in case; it helps debugging hard-to-trace bugs

--- OR ----

//B:
unsigned char buffer[sizeof(Cell)];
cell = new (buffer) (row, col);
[...]
cell->~Cell();
cell = 0; // just in case; it helps debugging hard-to-trace bugs

But you can't mix the two syntaxes, you can't construct with the
standard new operator and then call the destructor explicitly. I
recommend that you change your MCell destructor to

~MCell() { delete _cell; }

I also recommend that you stop using names beginning with an underscore,
as it may conflict with reserved words and other internal definitions,
although this is most likely not related to your problem.

Tamas
 
A

andrew.bell.ia

Thanks for your feedback. I did figure out the problem -- things were
getting deleted more than once. I just didn't understand the way that
things were manifesting themselves with the exception.

It is OK to explicitly call the dtor even if you have new'ed the
object. It just isn't usually necessary or helpful. Microsoft was
doing this in their example code that marries managed and unmanaged
code. Heck, I wasn't sure what they were thinking, so I thought I
would try it too. I did have a new/delete pair in my code originally.

Leading underscores certainly don't violate any language constraint.
Leading double underscores are reserved. Leading underscores are
reserved by C implementations, but since I use them to denote member
variables, it isn't an issue. Been doing it for many years on many
platforms without a single problem. As you said, this was not related
to my problem:)

Thanks again,

-- Andrew Bell
 
T

Tamas Demjen

It is OK to explicitly call the dtor even if you have new'ed the
object.

Except it's going to leak, because nobody deletes the object's memory.
The destructor certainly doesn't delete any memory.
Leading underscores certainly don't violate any language constraint.

There *is* a very real possibility that you get into a conflict, it's
not just a style issue.

http://www.informit.com/articles/article.asp?p=360435&seqNum=3&rl=1
Herb Sutter writes: "Never, ever, ever create names that begin with an
underscore or contain a double underscore; they're reserved for your
compiler and standard library vendor's exclusive use so that they have
names they can use without tromping on your code."

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top