【问题标题】:Base class pointers and segmentation error基类指针和分段错误
【发布时间】:2019-11-29 20:43:43
【问题描述】:

以下代码编译但运行时出现分段错误。我使用的是动态内存 主要使用指向派生类对象的基类指针,并且在运行时会出错。

#include <iostream>
using namespace std;

class Base {
public:
  int b;
  int b1;
  Base() : b(0), b1(0) { cout << "Base constructor" << endl; }
  virtual void Input() {
    cout << "Enter number b : ";
    cin >> b >> b1;
    // return *this;
  }
  virtual ~Base() {}
};
class Derived : public Base {
public:
  int d;
  // Constructor
  Derived() : d(0) { cout << "Derived constructor" << endl; }
  void Input() {
    Base::Input();
    cout << "Enter number d : ";
    cin >> d; //>> d1;
    // return *this;
  }
  ~Derived() {}
};

int main() {
  Base *s = new Derived[2];
  // When complexity of data members increases this line causes
  // segmentation fault
  s[1].Input(); // Here the problem

  delete[] s;
}

【问题讨论】:

  • 您能否礼貌地显示错误发生的位置?
  • Base *s = new Derived[2]。危险威尔罗宾逊!
  • 您不能创建 Derived 数组并使用 Base 指针访问该数组。
  • 如果你想要一个指针数组,你应该使用new两次。
  • 仅仅因为编译的东西意味着它是一个有效的 C++ 程序。

标签: c++


【解决方案1】:

你不能这样做:

Base* s = new Derived[2];

s 基本上被认为是Base 实例的数组,而Derived 的实例存储在里面。

您要么需要创建一个指向Base 的指针数组,然后用指向动态创建的Derived 对象的指针填充它(请参阅this question),或者最好使用向量:

std::vector<std::unique_ptr<Base>> s;
s.push_back(std::make_unique<Derived>());
s.push_back(std::make_unique<Derived>());

【讨论】:

    【解决方案2】:

    标准说(引自最新草案):

    [expr.delete]

    ...在数组删除表达式中,如果要删除的对象的动态类型与其静态类型不同,则行为未定义。

    您通过指向基类型的指针进行数组删除:您的程序的行为未定义。

    【讨论】:

      【解决方案3】:

      如果你会执行这些语句

      std::cout << "sizeof( Base ) = " << sizeof( Base ) << '\n';
      std::cout << "sizeof( Derived ) = " << sizeof( Derived ) << '\n';
      

      然后可以看到如下输出

      sizeof( Base ) = 16
      sizeof( Derived ) = 24
      

      所以类的大小是不同的。

      在这个表达式中

      s[1]
      

      这里用到了指针算法。表达式的计算方式类似于

      *( s + 1 )
      

      反过来又可以像这样重写

      *reinterpret_cast<Base *>( ( char * )s + sizeof( Base ) )
      

      因为指针s的静态类型是Base *

      因此,这个表达式 ( char * )s + sizeof( Base ) 不是指向 Derived 类型的第二个元素的指针,因为没有使用子表达式 sizeof( Derived ),而是使用了子表达式 sizeof( Base )

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-02
        • 2013-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多