以下程序会导致段错误。 从打印中我看到崩溃之前没有调用 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++ 编译器。
以下程序会导致段错误。
程序导致段错误的原因是创建了新的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>());
}