【问题标题】:Error: double free or corruption (out): 0x00007fffffffddf0 ***错误:双重释放或损坏(输出):0x00007fffffffddf0 ***
【发布时间】:2016-10-12 17:10:47
【问题描述】:

我正在玩分层对象和指针,并编写了一个基类 Circle,然后是两个类 Cylinder 和 Sphere,它们都派生自 Circle。 当我运行程序时出现错误:双重释放或损坏(输出):0x00007fffffffddf0 ***

所以我尝试通过 GDB 运行代码。我发现当我调用Cylinder析构函数时发生错误,它调用Circle的虚拟析构函数。但是我不明白为什么会这样。 根据我的研究,当代码尝试释放不可用的内存时,似乎会发生这种错误。

我认为可能是 Cylinder 的析构函数导致了问题,因为它首先被调用,所以我在 main() 中注释掉了所有 Sphere 和 Circle 对象行,只使用了 Cylinder 代码。 当调用 Cylinder 指针的析构函数时,会导致分段错误,因此我试图访问超出范围的内存。

现在我彻底糊涂了。

这是我的代码:

#include <iostream>
#include <cmath>    // used for square
static constexpr float PI = 3.14159;

using namespace std;

class Circle{
protected:
    float radius;
public:
    float getRadius(){
        return radius;
    }
    void setRadius(float r){
        radius = r;
    }
    float calcCircleArea(){
        return PI * pow(radius, 2);
    }
    float calcCircumference(){
        return 2 * PI * radius;
    }
    Circle(){
        // default constructor
    }
    Circle(float rad){
        radius = rad;   // overloaded constructor 
    }
    virtual ~Circle(){  // virtual destructor
        cout << "Destroying Circle Constructor" << endl;
    }
};

class Cylinder: public Circle{
private:
    float height;
public:
    float getHeight(){
        return height;
    }
    void setHeight(float h){
        height = h;
    }
    float calcVol(){
        float circleArea = calcCircleArea();
        float vol = circleArea * height;
    }
    float calcSurfaceArea(){
        float circum = calcCircumference();
        float circleArea = calcCircleArea();
        float cylSurfArea = (circleArea *2) + (circum * height);
    }
    Cylinder(){}    // default constructor

    Cylinder(float r, float h){ // overloaded constructor
        radius = r;
        height = h;
    }
    ~Cylinder(){    // destructor
        cout << "Destroying Cylinder Constructor" <<endl; 
    }
};

class Sphere : public Circle {
public:
    float calcSurfaceArea(){
        float r = getRadius();
        return 4* PI * pow(r,2);
    }
    float calcVol(){
        float r = getRadius();
        return (4.0/3.0) * PI * pow(r,3);
    }
    Sphere(){}  // default constructor

    Sphere(float r){
        radius = r;
    }
    ~Sphere(){  // destructor
        cout << "Destroying Sphere Constructor" << endl;
    }
};

int main(){
    cout << "Enter radius of circle and height of cyl:" << endl;
    float r;
    float h;
    cin >> r >> h;
    Sphere s1(r);
    Cylinder cyl1(r,h);
    Circle cir1(r);

 //****************************
 //     Set up pointers
 //****************************
    Circle *circPtr;
    circPtr = &cir1;
    Sphere *sPtr;
    sPtr = &s1;
    Cylinder *cylPtr;
    cylPtr = &cyl1;

    cout << "Sphere vol : " << sPtr->calcVol() << endl;
    cout << "Sphere SA : " << sPtr->calcSurfaceArea() << endl;

    cout << "Cyl vol : " << cylPtr->calcVol() << endl;
    cout << "Cyl SA : " << cylPtr->calcSurfaceArea() << endl;

    cout << "Circle area : " << circPtr->calcCircleArea() << endl;
    cout << "Circle circum : " << circPtr->calcCircumference() << endl;

    cout << "sphere RADIUS : " << sPtr->getRadius() << endl;
    cout << "cyl pointer VOLUME : " << cylPtr->calcVol() << endl;
    cout << "circ pointer AREA: " << circPtr->calcCircleArea() << endl;

    delete cylPtr;
    delete sPtr;

    return 0;
}

【问题讨论】:

  • Ehhrm,你为什么使用delete 而你从未使用过new?我强烈建议您阅读dynamic memory management
  • 另外,将CylinderCircle 派生出来没有意义,因为圆柱体不是 一种(特殊的)圆圈。你做错了(TM)。你应该得到一本不错的面向对象编程的书,并阅读isa 关系。

标签: c++ pointers object gdb


【解决方案1】:

您在堆栈上分配圆柱体和球体,然后在指向它们的指针上调用 delete。这将破坏您的对象两次。一次当你调用 delete 时,一次当它们超出范围时(主要结束)。

不要对不是用 new 创建的对象调用 delete。特别是不要对栈对象的地址调用delete。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多