free():检测到双重释放

问题描述 投票:0回答:2

我在编写这段代码时遇到了麻烦。我相信我的代码中没有语法错误,但我仍然没有得到所需的输出。

#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;
}

这是我期待的输出:

Circle with size 5 and radius 3
Shape with size 7

这是我收到的输出:

Circle with size 5 and radius 3
free(): double free detected in tcache 2
Aborted
c++ free
2个回答
0
投票

/*要修复代码,您可以从 Circle 的析构函数中删除 delete[] 数据语句,或者为 Shape 类定义复制构造函数和复制赋值运算符。这是后一个选项的示例: */

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
投票

问题在于如何删除主函数中的对象。因为您正在使用多态性,所以您应该指定向量来携带 Shape 指针而不是 Shape* 指针。这是正确的代码:

1.基类形状:

 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;
};

这是Shape的基类。它有一个构造函数,用于初始化动态分配的数组数据,其值从 0 到 size-1。析构函数负责释放为数据分配的内存。 printInfo 函数被声明为虚拟函数,使其具有多态性。

  1. 派生类圈:
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;
};

这是继承自Shape类的派生类Circle。它有自己的构造函数,用于初始化基类并设置半径。析构函数隐式调用基类析构函数。 printInfo 函数被重写以提供有关圆的特定信息。

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

该函数获取 Shape 对象的引用并调用其 printInfo 函数。它被设计为与多态性一起工作,允许它打印有关传递给它的任何派生类对象的信息。

  1. 主要功能:
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;
}

在主函数中,创建了一个指向 Shape 对象的指针向量。 Circle 对象和 Shape 对象是动态分配的,并且它们的指针被添加到向量中。然后,循环遍历向量,为每个形状调用 printShapeInfo 并删除动态分配的对象

© www.soinside.com 2019 - 2024. All rights reserved.