分配C ++指针 - >错误:未分配释放的指针

时间:2013-03-27 21:21:47

标签: c++ pointers malloc free destructor

我有一个析构函数,用于检查是否已经分配了指针,如果有,则将其删除:

ShadeRec::~ShadeRec(){

    cout << "before deleting ShadeRec" << endl;
    if(material){
        cout << material << endl;
        delete material;
        material = NULL;
    }
    cout << "after deleting ShadeRec" << endl;
}

第一个指针经过罚款,然后第二个指针给我错误。

我已经使用cout进行了检查,并且指针内部有一些内容,因为它进入了if语句,这是有道理的...所以为什么它会给我错误?

构造

ShadeRec::ShadeRec(World& world)
    :   hit(false),
        material(NULL),
        hitPoint(),
        localHitPoint(),
        normal(),
        ray(),
        depth(0),
        colour(0),
        t(0.0),
        w(world)
{}

ShadeRec::ShadeRec(const ShadeRec& sr)
    :   hit(sr.hit), 
        material(sr.material), 
        hitPoint(sr.hitPoint), 
        localHitPoint(sr.localHitPoint), 
        normal(sr.normal), 
        ray(sr.ray), 
        depth(sr.depth), 
        colour(sr.colour), 
        t(sr.t),
        w(sr.w)
{}

材料运营商=

Material& 
Material::operator= (const Material& rhs) {
    if (this == &rhs)
        return (*this);

    return (*this);
}

Matte是Material的孩子:

Matte* matte1 = new Matte;

这两个:

Matte& operator= (const Matte& rhs);

virtual Material* clone(void) const;

2 个答案:

答案 0 :(得分:4)

最有可能的是:

  • materialShadeRec
  • 的成员变量
  • ShadeRec的构造函数接受/设置指针
  • 未定义copy-ctor,如果是,只是复制指针,创建它指向的对象的新实例。
  • 至少有两个ShadeRec个实例,可能会将其复制为参数或返回值。
  • 第一个dtor删除对象并设置自己的指针NULL
  • 第二个dtor适用于另一个对象,指针仍然设置
  • 的Bam <!/ LI>

要使其可见,还要在您的dtor中打印this,您会看到它是ShadeRec的另一个实例。


编辑后:这就是这一行:

material(sr.material),

应该创建对象的副本,而不仅仅是复制普通指针。另一个选项,通常更可取的是使用std::shared_ptr(如果您可以使用C ++ 11,否则请查看boost::shared_ptr),但要注意ShadeRec的副本将共享相同的内容材料实例。

鉴于您目前所显示的内容,请使用

替换copy-ctor中的上述行
material(sr.material->clone()),

看看它是否有效。

答案 1 :(得分:2)

<强>问题

您没有定义深层复制构造函数。当您复制一个ShadeRec对象时,指针会被复制,因为它们会导致两个类之间发生冲突。

使用时如:

ShadeRec a;
ShadeRec b(a);

两个实例包含相同的地址,这意味着当第一个实例正确释放其指针时,第二个仍然必须释放其指针(已经被另一个释放)。

解决方案示例

这是一个正确的深拷贝构造函数的示例。 考虑material是指向动态分配的Material对象的指针,并且Material类具有正确定义的复制构造函数:

ShadeRec::ShadeRec(const ShadeRec& sr)
    :   hit(sr.hit), 
        material(0), // <--- NULL 
        hitPoint(sr.hitPoint), 
        localHitPoint(sr.localHitPoint), 
        normal(sr.normal), 
        ray(sr.ray), 
        depth(sr.depth), 
        colour(sr.colour), 
        t(sr.t),
        w(sr.w)
{
    if (sr.material)
        material = new Material(*(sr.material));
}

以下是如何编写正确的赋值运算符的示例:

Material& 
Material::operator= (const Material& rhs) {
    if (this != &rhs) {
        if (material)
            delete material;
        // make member per member assignments here
        material = new Material(*(rhs.material));
    }
    return (*this);
}

更多

如果可以的话,你应该使用智能指针,从C ++ 11开始,它在STL上实现为std::shared_ptr,或者在C ++ 11之前,在boost库中可用{{1} }}