【问题标题】:Segmentation Fault with delete even using virtual destructor即使使用虚拟析构函数也有删除的分段错误
【发布时间】:2011-07-20 14:10:44
【问题描述】:

我在删除对象时遇到分段错误,被基类的指针引用,即使我已经声明了虚拟的析构函数!

这是我的代码

class Shape
{
    public:
        virtual ~Shape()
        {
            cout<<"Shape destructor is called!"<<endl;      
        }

};    

class Line : public Shape
{
    public:
    ~Line()
        {
        cout<<"Line destructor is called!"<<endl;       
    }

};

int main()
{
Line myLine;
Shape* myShapePtr  = &myLine; //Line A

delete myShapePtr;
}

`

输出

调用了行析构函数!

形状析构函数被调用!

./runCP.sh: line 2: 2915 Segmentation fault ./a.out

我知道在 A 行中,对象被切片,这就是我收到此错误的原因。但是,我无法弄清楚对象切片是如何导致分段错误的。

如果对象已经被切片,那么虚拟析构函数肯定没有被调用,但这里也调用了虚拟析构函数。

请帮助我理解这一点。

【问题讨论】:

  • 切片并不像你想象的那样。

标签: c++


【解决方案1】:

你只能delete一个用new分配的对象。

myShapePtr 不指向分配有new 的对象,它指向myLine,这是一个局部变量。

作为局部变量,myLine 具有自动存储期限。当到达结束声明它的块的} 时,它将被自动销毁。

【讨论】:

    【解决方案2】:

    您只能在使用new 创建的对象上使用delete,在其他任何东西上使用delete,包括局部变量,都是未定义的行为。

    【讨论】:

      【解决方案3】:

      您不能删除堆栈中的对象。你必须先用new 实例化它:

      Shape* MyShapePtr = new Line();
      delete MyShapePtr;
      

      【讨论】:

        【解决方案4】:

        您在堆栈上声明了myLine。在 C++ 中,它会自动在超出范围 (}) 时被破坏,因此删除它是不正确的代码。

        您应该只(并且始终)在从new 返回的内存上使用delete。

        【讨论】:

          【解决方案5】:

          如果您在面试时遇到过这个问题,请通过重载delete operator 来安抚面试官!

          【讨论】:

            猜你喜欢
            • 2013-11-01
            • 1970-01-01
            • 2020-12-27
            • 2012-04-13
            • 2014-10-29
            • 2014-06-23
            • 2022-01-01
            相关资源
            最近更新 更多