dimanche 5 juin 2022

C++ Program crashes during destruction phase after adding two pointer arrays using operator+ overload

This program crashes during the destruction phase, I narrowed the problem down to the second forloop in the operator+

Quad, Circle and Square copy CTORs just pass the information up to a Shape CTOR that holds a name char*

ShapesContainer shapes;

Circle* c1 = new Circle( 3, "Circle 1" );
Square* s1 = new Square( 1, 1, 1, 1, "Square 1" );
Quad* q1 = new Quad( 2, 2, 2, 2, "Quad 1" );

shapes.addShape( c1 );
shapes.addShape( s1 );
shapes.addShape( q1 );
// shapes is an instance of ShapesContainer
// Which has a few shape objects in its m_arr pointer array
ShapesContainer newShapesContainer = shapes + shapes;

// ShapesContainer.cpp
// int m_size
// Shape** m_arr


ShapesContainer::ShapesContainer() {
    m_size = 0;
    m_arr = new Shape*;
}

ShapesContainer::ShapesContainer(const ShapesContainer &other) {
    m_size = 0;
    m_arr = new Shape*;
    for (int i = 0; i < other.m_size; i++) {
        addShape(other.m_arr[i]);
    }
}

ShapesContainer::~ShapesContainer() {
    if (m_arr == nullptr) return;
    for (int i = 0; i < m_size; i++) {
        delete m_arr[i];
    }
}

// add a new shape (deep copy) to the end of array
void ShapesContainer::addShape( Shape* newShape ) {
    Circle* c = dynamic_cast<Circle*>(newShape);
    // newShape can only be Circle or Quad
    if (c) {
        m_arr[m_size++] = new Circle(*c); // copy CTOR
        return;
    }
    Quad* q = dynamic_cast<Quad*>(newShape);
    if (q) {
        m_arr[m_size++] = new Quad(*q); // copy CTOR
        return;
    }
}

// returns a new allShape with all elements located at this and other
ShapesContainer ShapesContainer::operator+( const ShapesContainer& other ) const {
    ShapesContainer resultShape;
    for (int i = 0; i < m_size; i++) {
        resultShape.addShape(m_arr[i]);
    }
    // When this for loop is deleted this program doesn't crash
    for (int i = 0; i < other.m_size; i++) {
        resultShape.addShape(other.m_arr[i]);
    }
    return resultShape;
}
// Shape DTOR
Shape::~Shape() {
    if (m_shapeName != nullptr) {
        delete [] m_shapeName;
        s_totalNumOfShapes--;
    }
}

When I remove the second forloop in the operator+ everything runs just fine, but when I do have it in it crashes in this order:

  1. ShapesContainer DTOR finishes for the newShapesContainer instance
  2. ShapesContainer DTOR finishes for the shapes instance
  3. Program crashes

I've tried debugging this further, and it seems like the copy CTORs work as expected (I've literally compared memory addresses between these objects) but still it seems like adding another object to the resultShape instance causes it to crash.

I've also tried creating a different instance of ShapesContainer and add that one to the shapes instance but the same error occurres.

Aucun commentaire:

Enregistrer un commentaire