C++ - 尝试理解虚函数、虚表以及为什么这个程序会出现段错误

问题描述 投票:0回答:1
  • 以下程序会导致段错误。 从打印中我看到崩溃之前没有调用 Dtor。

  • 在 gdb 中我看到每个 Y 对象都包含一个指向其 vtable 的指针。 因此,当尝试删除对象时,程序将在 Y 的 vtable 中搜索 Dtor。

  • 但是,我们使用的是指向 Y 对象的 X 指针 -

  • 所以我的理论是,程序尝试访问 Y 的 vtable 中与 X 的 Dtor 相对应的条目,因为(这就是我想要得到的确认)它计算偏移量(从 vtable 的开头开始) 使用函数的名称('~X'因为指针是X类型),这使得它尝试访问无效地址。

  • 所以问题是 - 距离 vtable 开头的偏移量是如何计算的?真的是从函数的名称来看的吗?

  • 请告诉我你们的想法,如果我说的是完全废话请纠正我XD

  • 谢谢一堆:)

class X
{
public:
    virtual ~X() {}
    
private:
    double m_a;
};

class Y: public X
{
private:
    int m_b;
};

int main()
{
    X *xp = new Y[5];
    delete[] xp;

    return 0;
}

还有两件事我想弄清楚:

  • 为什么当我将 m_b 的类型更改为 double(或任何其他 8 字节长类型)时,程序不会崩溃?

  • 为什么当我将 X 的 Dtor 设置为非虚拟时,程序也不会崩溃?

  • p.s - 我正在使用 C++ 98 和 g++ 编译器。

c++ segmentation-fault destructor virtual vtable
1个回答
0
投票

以下程序会导致段错误。

程序导致段错误的原因是创建了新的Y[5],

allocating an array of 5 Y objects
,存储在X*类型的指针中的是Y对象。然后调用delete[]。由于 X 有一个虚拟析构函数,因此运行时会尝试为数组中的每个 X 对象调用析构函数。但它没有正确处理 Y 对象的析构函数,这会导致段错误。

您可以尝试使用

std::vector
derived objects Y
存储在
base class pointer X*
中。

std::vector<std::unique_ptr<X>> objects;
for (int i = 0; i < 5; ++i) {
    objects.push_back(std::make_unique<Y>());
}
© www.soinside.com 2019 - 2024. All rights reserved.