Wednesday, March 7, 2012

Assertion failed error while resizing a vector in a plug-in algorithm

I got an Assertion failed error while resizing a vector in a plug-in algorithm.

In order to isolate the problem I created a simple model class in Navigator.h file as shown below:

//========================= begin code =======================

class CStateStats
{
public:
DOUBLE m_dblSum;
DOUBLE m_dblSqrSum;
public:
CStateStats()
{
m_dblSum = 0.0;
m_dblSqrSum = 0.0;
}
};

class CAttStats : public DMHALLOC
{
public:
dmh_vector<CStateStats> vstatestats;
public:
CAttStats() : vstatestats (*this)
{
}
};

//========================= end code =======================

The access to DMHALLOC is provided in that class and in Navigator class as shown below:

//========================= begin code =======================

class ATL_NO_VTABLE NAVIGATOR :

public DMHALLOC,

public CComObjectRootEx<CComMultiThreadModel>,

public CComCoClass<NAVIGATOR, &CLSID_NAVIGATOR>,

public ISupportErrorInfo,

public IDMAlgorithmNavigation

{

public:

NAVIGATOR() : _viAttributeOutput(*this), _vCAttStats(*this)

//========================= end code =======================


I succeded making room for _vCAttStats vector, but when I tried providing room for the vectors of the vector I got an Assertion failed error (file dmhallocator.h Line:56 Expression assert(_dmhalloc._spidmmemoryallocator != NULL)). Please, see the code below, included in NAVIGATOR::GetNodeArrayProperty function:

//========================= begin code =======================

_vCAttStats.resize (2); // <<<<< succeeded here!

// make space for the states

_vCAttStats[0].vstatestats.resize(ulStates); // <<<<<<< assertion failed here!

//========================= end code =======================

I tried using a vector-of-vector approach and I also succeeded.

But I have to use that kind of structure: a vector of class with a vector inside.

I think I must provide a similar approach of vector-of-vector existing in DmhVector.h but I don't know how to do it.

I would apreciate any help.

hello,Claudio

It looks like:

- the original DMHALLOC (containing the allocator pointer), NAVIGATOR is passed properly to the vector of CAttStats, _vCAttStats and used correctly in resizing it

- during resize, STL calls the default constructor for CAttStats , which does not take any argument. Consequently, the CAttStats DMHALLOC instance does not contain an allocator pointer

- _vCAttStats[0].vstatestats.resize(ulStates); attempts to resize the vstatestats vector, which does not have a properly initialized DMHALLOC , hence the assertion that fails

To confirm my hypothesis in your code, try to use _vCAttStats[0].vstatestats.get_allocator() right before calling resize. It is likely NULL or uninitialized (well, not the actual object which is a reference, but the IDMMemoryAllocator pointer it contains).

The simplest and most reliable solution is:

- do not derive CAttStats from DMHALLOC

- use, instead, an IDMMemoryAllocator member inside the CAttStats

- explicitly set that member to the current allocator before using vstatestats

- use IDMMemoryAllocator->Alloc( n*sizeof(CStateStats) ) to get a C-style buffer of state stats which can be freed in the destructor of CAttStats with IDMMemoryAllocator->Free

Hope this helps

|||

Hi Bogdan,

Thanks for you help.

I suceeded using your suggestions.

The drawbacks of this approach are that I have to explicitly initialize vstatestats because the class constructor is not called anymore when I provide room for the buffer and I don't have anymore the vector facilities. Am I correct?

No comments:

Post a Comment