Ryan
Ryan

Reputation: 241

Debug Assertion Failed! C++ VS2012 - Template Class

I'm doing an assignment and I've put together a template class for a Vector, and now have inherited it (per the assignment) to make it a sort-able. At the very end of the void SearchableVector<T>::add(T itemToAdd) method it throws a Debug Assertion Failed! error. The full text of the error is as follows:

---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Debug Assertion Failed!

Program: ...tudio 2012\Projects\COSC 1437\Program 10\Debug\Program 10.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgdel.cpp
Line: 52

Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

---------------------------
Abort   Retry   Ignore   
---------------------------

I've looked around and I realize this is a pretty common error usually related to memory management. Often calling delete on inappropriate things. I must be doing something similar because I'm getting the error, but I cannot find what I'm doing wrong. If you could help me out and/or point me in the right direction that would be much appreciated.

Main.cpp

#include "SimpleVector.h"
#include "SearchableVector.h"
#include <stdlib.h>
#include <time.h>
void main()
{
        srand (time(NULL));
        SearchableVector<int> v(0);
        for (int i = 0; i < 20; i++)
        {
            v.add(rand() % 20);
        }
        v.print();
}

SimpleVector.h

#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
#include <iostream>
#include <stdexcept>
#include <iomanip>
using namespace std;

template<class T>
class SimpleVector {
public:
    //Constructors
    SimpleVector();   //default constructor, size 0
    SimpleVector(int); //parameterized constructor with default size
    SimpleVector(const SimpleVector& a); //copy constructor
    ~SimpleVector(); //destructor

    T& operator[](int) const;
    SimpleVector<T>& operator=(SimpleVector<T>);
    const bool operator==(SimpleVector&) const;
    void push_back(T);
    T& pop_back();
    T& getElement(int);
    int getSize() const;
    void print() const;
protected:
    int size;
    T* internalArray;
    void SimpleVector<T>::swap(SimpleVector&);
};
template<class T>
SimpleVector<T>::SimpleVector()
{
    size = 0;
    internalArray = nullptr;
}

template<class T>
SimpleVector<T>::SimpleVector(int sizeOfArray) 
{
    if (sizeOfArray < 0) throw "SimpleVector size must not be less than 0";
    internalArray = new T[sizeOfArray]();
    size = sizeOfArray;
}

template<class T>
SimpleVector<T>::SimpleVector(const SimpleVector& vectorToCopy):size(vectorToCopy.getSize()), internalArray( new T[vectorToCopy.getSize()] )
{
    for (int i = 0; i < size; i++)
        internalArray[i] = vectorToCopy.internalArray[i];
}
template<class T>
SimpleVector<T>::~SimpleVector() {
    //cout << "Destructor called" << std::endl;
    delete[] internalArray;
}

template<class T>
T& SimpleVector<T>::operator[](int i) const {
    if (i<0 || i>=size) throw "Vector::operator[] : index is out of range";
    return internalArray[i];
}

template<class T>
SimpleVector<T>& SimpleVector<T>::operator=(SimpleVector<T> rightSide) { 
    rightSide.swap(*this);
    return *this;
}

template<class T>
const bool SimpleVector<T>::operator==(SimpleVector& right) const {
    if (size() != right.size())
        return false;
    else {
        for (int i = 0; i < size(); i++){
            if (internalArray[i] != right[i])
                return false;
        }
    }
    return true;
}

template<class T>
void SimpleVector<T>::push_back(T itemToAdd) {
    SimpleVector<T> temp(size + 1);
    for (int i = 0; i < size; i++)
        temp[i] = internalArray[i];
    temp[size] = itemToAdd;
    temp.swap(*this);
}

template<class T>
T& SimpleVector<T>::pop_back()
{
    SimpleVector<T> temp(size - 1);
    for (int i = 0; i < size; i++)
        temp[i] = internalArray[i];
    T pop = internalArray[size-a];
    temp.swap(*this);
    return pop;
}

template<class T>
T& SimpleVector<T>::getElement(int indexToGet)
{
    return internalArray[indexToGet];
}

template<class T>
int SimpleVector<T>::getSize() const {
    return this->size; 
}

template<class T>
void SimpleVector<T>::print() const
{
    for (int i = 0; i < size; i++)
    {
        std::cout << internalArray[i];
        if (i!=(size-1))
            std::cout << ",";
        else
            std::cout << std::endl;
        if (i%10 == 0 && i!=0)
            std::cout <<std::endl;
    }
}

template<class T>
void SimpleVector<T>::swap(SimpleVector& other)
{
     std::swap(internalArray, other.internalArray);
     std::swap(size, other.size);
}
#endif

SearchableVector.h

#ifndef SEARCHABLEVECTOR_H
#define SEARCHABLEVECTOR_H
#include "SimpleVector.h"
template<class T>
class SearchableVector : protected SimpleVector<T>
{
public:
    SearchableVector(int);
    SearchableVector(const SearchableVector&);
    ~SearchableVector();
    void add(T);
    T getElement(int);
    int getSize() const;
    void print() const;
    int search(T);
};
template<class T>
SearchableVector<T>::SearchableVector(int sizeOfArray) : SimpleVector(sizeOfArray)
{

}

template<class T>
SearchableVector<T>::SearchableVector(const SearchableVector& vectorToCopy) : SimpleVector(vectorToCopy)
{

}

template<class T>
SearchableVector<T>::~SearchableVector()
{
    delete[] internalArray;
}

template<class T>
void SearchableVector<T>::add(T itemToAdd)
{
    bool flag = false;
    SearchableVector<T> temp(size + 1);
    for (int i = 0; i < size; i++)
    {
        if ((itemToAdd <= internalArray[i]) && (flag == false))
        {
            temp[i] = itemToAdd;
            i++;
            flag = true;
        }
        temp[i] = internalArray[i];
    }
    if (flag == false)
        temp[size] = itemToAdd;
    temp.swap(*this);
} // !*******************! THROWS THE ERROR RIGHT HERE !*******************! 

template<class T>
T SearchableVector<T>::getElement(int elementToGet)
{
    return SimpleVector::getElement(elementToGet);
}

template<class T>
int SearchableVector<T>::getSize() const
{
    return SimpleVector::getSize();
}

template<class T>
void SearchableVector<T>::print() const 
{
    SimpleVector::print();
}

template<class T>
int SearchableVector<T>::search(T itemToSearchFor)
{

}

#endif

Upvotes: 0

Views: 114

Answers (1)

Yochai Timmer
Yochai Timmer

Reputation: 49251

First of all, when using inheritance, 99% of the time you should use a virtual destructor.

That's very important.

virtual ~SimpleVector();

When deleting an object, its base class destructor is called too.
And in your case you have delete[] internalArray; in both destructors.
Just leave that delete in the base class, because that member belongs to it, and it should take care of it.

Next time you encounter something like this, put a breakpoint near all the delete calls for that object type, then you can see which ones are called and in what order.

Upvotes: 2

Related Questions