为什么此删除会导致核心转储

Why does this delete cause a core dump?

本文关键字:核心 转储 删除 为什么      更新时间:2023-10-16

如果我不使用基类的指针,则此代码可以正常工作,然后删除基类Output的指针。 输出的析构函数被调用,并且似乎可以正常工作。 我在这里错过了什么吗?

// multiple inheritance
// Testing overload of muliple inheritance of pure virtual functions.
#include <iostream>
#include <string>
using namespace std;
class Polygon {
  protected:
    int width, height;
  public:
    Polygon (int a, int b) : width(a), height(b) {}
    ~Polygon() = default;
    virtual int area() = 0;
};
class Output {
  private:
    string* myString;
  public:
    Output() {
      myString = nullptr;
    }
    Output(const string& s) {
      myString = new string(s);
    }
    // This seems to work, but ther core dump happens right afterwards.
    ~Output() {
      cout << "delete called with: " << myString << 'n';
      if (myString != nullptr)
        delete myString;
    }
    virtual int area() = 0;
    void print () {
      cout << *myString << this->area() << 'n';
    }
};

class Rectangle: public Polygon, public Output {
  public:
    Rectangle (int a, int b) : Polygon(a,b), Output{"A Rectangle's area is: "} {}
    int area () {
     return width*height;
   }
};
class Triangle: public Polygon, public Output  {
  public:
    Triangle (int a, int b) : Polygon{a,b}, Output{"A Triangle's area is: "} {}
    int area ()
      { return width*height/2; }
};
int main () {
  Output * ptr1 = new Rectangle(4,5);
  Output * ptr2 = new Triangle(4,5);
  ptr1->print();
  ptr2->print();
  // Causes core dump.  
  delete ptr1;
  delete ptr2;
  return 0;
}

此代码有几个主要问题:

首先,不应为此使用多重继承。 这是完全不必要的,并且会导致很难追踪错误。

其次,在删除指针之前,您不需要测试nullptr - 它是多余的,因为delete已经这样做了。

第三,您的基类都没有虚拟析构函数。(您当前的错误)

第四,你在Output类中违反了 3 法则(并且可能需要在所有类中使用它)。

第五,假设string意味着std::string。 它没有理由成为string* - 只需使用std::string,避免必须分配和取消分配它。

我没有解决您的设计问题,但您的内存访问和多态问题已在此处修复。

#include <iostream>
#include <string>
using namespace std;
class Polygon 
{
  protected:
    int width, height;
  public:
    Polygon (int a, int b) : width(a), height(b) {}
    virtual ~Polygon() { } // needed!
    virtual int area() = 0;
};
class Output 
{
  private:
    std::string myString; // no need to be a pointer
  public:
    Output() {    }
    Output(const string& s) : myString(s) {   }
    virtual ~Output() {    } // also needed!
    virtual int area() = 0;
    void print () {
      cout << myString << this->area() << 'n';
    }
};

class Rectangle: public Polygon, public Output 
{
  public:
    Rectangle (int a, int b) : Polygon(a,b), Output{"A Rectangle's area is: "} {}
    int area () {
     return width*height;
   }
};
class Triangle: public Polygon, public Output  
{
  public:
    Triangle (int a, int b) : Polygon{a,b}, Output{"A Triangle's area is: "} {}
    int area ()
      { return width*height/2; }
};
int main () 
{
  Output * ptr1 = new Rectangle(4,5);
  Output * ptr2 = new Triangle(4,5);
  ptr1->print();
  ptr2->print();
  // Causes core dump.  
  delete ptr1;
  delete ptr2;
  return 0;
}

编辑:可以在此处找到实现所需程序的更好方法的示例。

您的OutputPolygon类析构函数也应该virtual

class Output {
  private:
    std::string* myString;
  public:
        // ...
    virtual ~Output() { 
 // ^^^^^^^
    }
};

另请注意:您可以简单地使用 std::string myString; 成员,而不是使用 std::string* 指针:

  private:
    std::string myString;

并留下为new string()delete myString;而烦恼,以应对任何情况。