删除指针的分段错误

segmentation fault for deleting a pointer

#include <iostream>
using namespace std;
class c1 {};
class c2 : public c1 {};
class c3 : public c1 {};
class c4 : public c2, public c3 {};

int main () {
  c4 *x1 = new c4;
  c3 *x2 = x1;
  delete x2; // segmentation fault
}

嗨,我想了解类型转换和继承,我发现了这个问题。我有一个指向最派生的 class 的指针,并且在删除时被类型转换(隐式)到中间任何 class,我认为它应该能够删除第一个新分配的 space .在某些编译器中,它看起来很好,但在 linux gcc 版本 4.7.2 (Debian 4.7.2-5) 中,它给出了分段错误。想不通,为什么?任何 help/pointer/suggestion 将不胜感激。

注-Class是以菱形问题的形式推导出来的。

这是未定义的行为。正如您所看到的,在某些情况下它可能看起来很好,但在某些情况下它不会。

至少基础 class c3(或 c1c2)应该有一个 virtual 析构函数。例如

class c3 : public c1 {
public:
    virtual ~c3() {}
};

按照标准,.3.5/3 Delete [expr.delete]:

(强调我的)

In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.

正在尝试删除 new 未返回的指针。对于基础 classes 的解决方案,请使用 virtual destructor。当您通过指向基 class 的指针删除对象时,基 class 需要一个 virtual 析构函数。

为了补充前面的答案,undefined 行为来自于将指针转换为基数 class 意味着(大多数情况下,但在您的示例中不是)slicing:调整(即递增)指针指向嵌入class.

的开头

因此,在递增的指针上调用 delete 时,您可能会释放部分内存并让其中的一些 悬空