views:

51

answers:

2

TL;DR

Boost-Test-Framework crashes with no error given while passing all tests and leaking all memory.

Test fails multiple times with mentioned destructor implementations. Clear function also throws heap error.

What are we doing wrong with the dtor?

TL;DR

This is pertaining to a college homework assignment, and my friend's solution to said problem. In order to get more aquainted with C-style pointers and a more low-level style of programming, we needed to implement our own dynamic array.

His assignment is complete and completely functional according to our teacher's 900-LOC Boost-Test Framework. The only problem is the crash (or heap error, as no real error message pops up) when the tests exit, or an implemented dtor is called.

His dynamic array uses three pointers: pFirst, pLast and pEnd, pointing to the first element of the array, to the one past the last element in the array, and pointing to the last not-yet allocated element in the array respectively.

His program passed as long as he didn't try to delete any pointers. This is a bad idea, but hey, it let him pass the assignment. For now.

My friend has tried several times to implement a destructor, but they both cause heap errors and cause the test-framework to fail.

// Teacher's recommended dtor.
Field::~Field()
{
    for(int i(0); i != this->size(); ++i)
        (pFirst+i)->~T();
    delete pFirst;
    pFirst = pLast = pEnd = NULL;
}

and

// My recommendation to friend.
Field::~Field()
{
    delete[] pFirst;
    pFirst = pLast = pEnd = NULL;
}

both crash with the same heap error.

Assertion failed: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

A typical chain of tests looks like:

BOOST_AUTO_TEST_CASE( TEST_clear )
{
    Field f( 3, 4.0f );
    f.clear();  // Error here IF we use delete in the clear method.
    BOOST_CHECK( f.size()==0 );
    BOOST_CHECK( f.capacity()==4 ); 
} // Error here; during destruction IF we have implemented the dtor.

The clear method emits the same error when we try to replace the array, so we just have:

void Field::clear()
{
    size_t capa = capacity();
    T *temp =pFirst;
    pFirst = new T[capa];
    pLast = pFirst;
    pEnd = pFirst+capa;
}

What are we doing wrong with the dtor, clear and in general when dealing with the deletion of pointers?

+2  A: 

Assertion failed: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) indicates heap corruption. Usually it happens when you write past the end of the allocated memory. I see the following issue in your code: in Field::clear you store the pointer to allocated memory in pFirst and immediately overwrite it by pLast. I think you should change it to pLast = pFirst;.

Teacher's recommended dtor makes no sense to me. If you allocate with new[] then deallocate with delete[], don't call each destructor separately and use delete.

vitaut
+1  A: 

If pFirst points to the first element of the array, then your "teacher's recommended dtor" is wrong. You'd need to say delete[] pFirst to deallocate the array.

But there are many issues which could be causing this, such as heap corruption caused by some other function. Try running this in a memory-corruption check program, like Valgrind, to see if you are overflowing your heap buffer.

Charles Salvia