繁体   English   中英

用于删除指针的分段错误

[英]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
}

嗨,我想了解类型转换和继承,我发现了这个问题。 我有一个指向最派生类的指针,并且对任何类中间进行了类型化(隐式),而删除时,我认为它应该能够通过第一个新删除已分配的空间。 在一些编译器中,它似乎很好,但在linux gcc版本4.7.2(Debian 4.7.2-5)中,它给出了分段错误。 无法弄清楚,为什么? 任何帮助/指针/建议将不胜感激。

注 - 类是以钻石问题的形式派生的。

这是未定义的行为。 正如您所见,在某些情况下它似乎运作良好,在某些情况下它不会。

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

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

根据标准, $ 5.3.5 / 3删除[expr.delete]

(强调我的)

在第一个备选( 删除对象 )中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为要删除的对象的动态类型的基类, 静态类型应具有虚拟析构函数或行为未定义

试图删除未由new返回的指针。 对于解决方案,使用基类的virtual destructor 通过指向基类的指针删除对象时,基类需要一个virtual析构函数。

要添加到上一个答案, undefined行为来自于将指针转换为基类意味着(大部分时间,但不是在您的示例中) 切片 :指针被调整(即递增)以指向开头嵌入式类。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM