free(): double free detected

107 views Asked by At

I am having trouble with programming this code. I believe that there is no syntax error in my code, yet I am still not getting the desired output.

#include <iostream>
#include <vector>

class Shape {
public:
    Shape(int size) : size(size) {
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = i;
        }
    }

    virtual ~Shape() {
        delete[] data;
    }

    virtual void printInfo() const {
        std::cout << "Shape with size " << size << std::endl;
    }

protected:
    int* data;
    int size;
};

class Circle : public Shape {
public:
    Circle(int size, int radius) : Shape(size), radius(radius) {}

    ~Circle() {

        delete[] data;
    }

    void printInfo() const override {
        std::cout << "Circle with size " << size << " and radius " << radius << std::endl;
    }

private:
    int radius;
};

void printShapeInfo(const Shape& shape) {
    shape.printInfo();
}

int main() {
    std::vector<Shape*> shapes;

    shapes.push_back(new Circle(5, 3));
    shapes.push_back(new Shape(7));

    for (const Shape* shape : shapes) {
        printShapeInfo(*shape);
        delete shape;
    }

    return 0;
}

This is the output I am expecting:

Circle with size 5 and radius 3
Shape with size 7

And this is the output I am receiving:

Circle with size 5 and radius 3
free(): double free detected in tcache 2
Aborted
2

There are 2 answers

1
Hassan Haris On

To fix your code, you can either remove the delete[] data statement from the Circle’s destructor, or define a copy constructor and a copy assignment operator for the Shape class. Here is an example of the latter option:

class Shape {
public:
Shape(int size) : size(size) {
    data = new int[size];
    for (int i = 0; i < size; ++i) {
        data[i] = i;
    }
}

// Copy constructor
Shape(const Shape& other) : size(other.size) {
    data = new int[size];
    for (int i = 0; i < size; ++i) {
        data[i] = other.data[i];
    }
}

// Copy assignment operator
Shape& operator=(const Shape& other) {
    if (this != &other) {
        delete[] data;
        size = other.size;
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = other.data[i];
        }
    }
    return *this;
}

virtual ~Shape() {
    delete[] data;
}

virtual void printInfo() const {
    std::cout << "Shape with size " << size << std::endl;
}

protected:
int* data;
int size;
};

class Circle : public Shape {
public:
Circle(int size, int radius) : Shape(size), radius(radius) {}

~Circle() {
    // No need to delete data here, it is done by the base class
}

void printInfo() const override {
    std::cout << "Circle with size " << size << " and radius " << radius << 
std::endl;
}

private:
int radius;
};

void printShapeInfo(const Shape& shape) {
shape.printInfo();
}

int main() {
std::vector<Shape*> shapes;

shapes.push_back(new Circle(5, 3));
shapes.push_back(new Shape(7));

for (const Shape* shape : shapes) {
    printShapeInfo(*shape);
    delete shape;
}

return 0;
}
0
Moiz Imran On

The issue is with how you delete the objects in the main function. Because you're using polymorphism, you should specify the vector to carry Shape pointers rather than Shape* pointers. This is the correct code:

1.Base Class Shape:

 class Shape {
    public:
        Shape(int size) : size(size) {
            data = new int[size];
            for (int i = 0; i < size; ++i) {
                data[i] = i;
            }
        }
    
    
        virtual ~Shape() {
            delete[] data;
        }
    
        virtual void printInfo() const {
            std::cout << "Shape with size " << size << std::endl;
        }

protected:
    int* data;
    int size;
};

This is the base class Shape. It has a constructor that initializes a dynamically allocated array data with values from 0 to size-1. The destructor takes care of freeing the memory allocated for data. The printInfo function is declared as virtual, making it polymorphic.

  1. Derived Class Circle:
class Circle : public Shape {

    public:
    
        Circle(int size, int radius) : Shape(size), radius(radius) {}
    
    
        void printInfo() const override {
            std::cout << "Circle with size " << size << " and radius " << radius << std::endl;
        }
    
    private:
        int radius;
};

This is the derived class Circle that inherits from the Shape class. It has its own constructor that initializes the base class and sets the radius. The destructor is implicitly calling the base class destructor. The printInfo function is overridden to provide specific information about the circle.

  1. printShapeInfo Function:
void printShapeInfo(const Shape& shape) {
    shape.printInfo();
}

This function takes a reference to a Shape object and calls its printInfo function. It is designed to work with polymorphism, allowing it to print information about any derived class object that is passed to it.

  1. main Function:
int main() {
    std::vector<Shape*> shapes;


    shapes.push_back(new Circle(5, 3));
    shapes.push_back(new Shape(7));

 
    for (const Shape* shape : shapes) {
        printShapeInfo(*shape);
        delete shape; // Delete each dynamically allocated object
    }

    return 0;
}

In the main function, a vector of pointers to Shape objects is created. A Circle object and a Shape object are dynamically allocated and their pointers are added to the vector. Then, a loop iterates through the vector, calling printShapeInfo for each shape and deleting the dynamically allocated objects