Dan Heinzel
Dan Heinzel

Reputation: 53

Visual Studio 2010, C++, "vector iterators Incompatible" during vector.clear()

Due to some craziness, I've been forced to upgrade to Microsoft Visual Studio 2010 Ultimate on a fresh install of Win7 Pro. I've reduced the code down to bare bones of structure and what in general is going on. I've heard this may be a bug in VS2010 in their STL implementation, and if so, am looking for a work-around. (EDIT: My original code worked fine in Visual Studio 2008.)

Here's the header file:

#include <iostream>
#include <vector>
using namespace std;

class ChildClass    //partition function for each
{
public:
    ChildClass();
    void Clear(void);
    vector<double> childrenvars;
    void PrintChildren(void);
    //long list of other variables
};
class ParentClass
{
    public:
    ChildClass variable;
    //other variables
    ParentClass();
    ~ParentClass();
};

And here's the source file:

#include "source.h"

ChildClass::ChildClass()
{
    Clear();
}
void ChildClass::Clear(void)
{
    childrenvars.clear();
    return;
}
void ChildClass::PrintChildren(void)
{
    cout << endl;
    for(unsigned int i=0; i<childrenvars.size(); i++)
        cout << childrenvars[i] << " ";
}
ParentClass::ParentClass()
{
    this->~ParentClass();
}
ParentClass::~ParentClass()
{
    this->variable.childrenvars.clear();
}

int main(void)
{
    ParentClass* ParVar = new ParentClass[5];
    for(unsigned int numiter = 0; numiter < 3; numiter++)
    {
        for(unsigned int i=0; i<5; i++)
        {
            for(unsigned int j=0; j<i; j++)
                ParVar[i].variable.childrenvars.push_back(j);
            ParVar[i].variable.PrintChildren();
        }
        for(unsigned int i=0; i<5; i++)
            ParVar[i].variable.Clear();
    }
    delete [] ParVar;
    int wait;
    std::cin >> wait;
    return(0);
}

Compiling in release gives a predictable and functional:

(blank)
0
0 1
0 1 2
0 1 2 3

0
0 1
0 1 2
0 1 2 3

0
0 1
0 1 2
0 1 2 3

Compiling in debug mode gives:

(blank)
0
0 1
0 1 2
0 1 2 3

Debug Assertion Failed... vector iterators incompatible.

It is failing on the first time it calls the .Clear() function. This occurs even if changing the clear for loop to start at 1,2, etc. The error seems to be resulting as .clear() calls .erase(begin(), end()). It really hates it when nothing has been put in the vector and it's already empty. Interestingly, here's what I see under the autos when the clear loop starts at 2 in the erase(const_iterator _First_arg, const_iterator_Last_arg).

_First_arg = 0, as expected.

_Last_arg = -2.53...e-098

this:

size: 2

capacity: 2

0: 0.0000...

1: 1.000....

The first vector starts at: 0x002648e8 The last vector starts at: 0x002648f8 (though I think due to the end(), this is actually one beyond the last, which would make sense with 8 byte doubles).

Aside from going to the preprocessor definitions and setting _ITERATOR_DEBUG_LEVEL=0 to turn these "features" off (I actually would like to know if I accidentally do screw up), anybody have any ideas as to what the actual cause is and how to fix this? While I do have some redundant clears in there, I don't imagine that would be the source of this issue. Especially considering the code never even gets to the destructors in the first place.

Thanks in advance!

~Dan

Upvotes: 1

Views: 3894

Answers (2)

CB Bailey
CB Bailey

Reputation: 792637

ParentClass::ParentClass()
{
    this->~ParentClass();
}

A destructor is not a normal function, it is a special function. If you call the destructor on an object it is completely destroyed including all its bases and members. Here you are destroying the ParentClass object before it has been fully constructed. Any attempt to use the object is likely to cause problems such as the one flagged by the error message that you see.

If you want to share code between the destructor and another function you should but the code in a separate function and call that from the destructor and the other function. In almost all application code you should never need to call a destructor explicitly.

std::vector is constructed empty by default and cleans up on destruction so the ChildClass constructor and the ParentClass constructor and destructor are all redundant in your example and can be omitted.

Upvotes: 2

Fraser
Fraser

Reputation: 78398

Not sure what the intent is here, but if you remove this->~ParentClass(); it works.

Upvotes: 1

Related Questions