向向量添加时析构函数内部的双重释放 [英] Double Free inside of a destructor upon adding to a vector

查看:83
本文介绍了向向量添加时析构函数内部的双重释放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嘿,我在鼓机上工作,矢量有问题。

每个序列都有一个样本列表,这些样本以向量的形式进行排序。然而,当样本在向量上被PUSH_BACK时,该样本的析构函数被调用,并导致双重释放错误。

以下是示例创建代码:

class XSample
{
  public:
    Uint8 Repeat;
    Uint8 PlayCount;
    Uint16 Beats;
    Uint16 *Beat;
    Uint16 BeatsPerMinute;

    XSample(Uint16 NewBeats,Uint16 NewBPM,Uint8 NewRepeat);
    ~XSample();

    void GenerateSample();

    void PlaySample();
};

XSample::XSample(Uint16 NewBeats,Uint16 NewBPM,Uint8 NewRepeat)
{
    Beats = NewBeats;
    BeatsPerMinute = NewBPM;
    Repeat = NewRepeat-1;
    PlayCount = 0;

    printf("XSample Construction
");
    Beat = new Uint16[Beats];
}

XSample::~XSample()
{
    printf("XSample Destruction
");
    delete [] Beat;
}

和在向量中创建每个样本的‘Dynamo’代码:

class XDynamo
{
  public:
    std::vector<XSample> Samples;

    void CreateSample(Uint16 NewBeats,Uint16 NewBPM,Uint8 NewRepeat);
};

void XDynamo::CreateSample(Uint16 NewBeats,Uint16 NewBPM,Uint8 NewRepeat)
{
    Samples.push_back(XSample(NewBeats,NewBPM,NewRepeat));
}

以下是main():

int main()
{
    XDynamo Dynamo;

    Dynamo.CreateSample(4,120,2);
    Dynamo.CreateSample(8,240,1);

    return 0;
}

程序运行时会发生以下情况:

Starting program: /home/shawn/dynamo2/dynamo 
[Thread debugging using libthread_db enabled]
XSample Construction
XSample Destruction
XSample Construction
XSample Destruction
*** glibc detected *** /home/shawn/dynamo2/dynamo: double free or corruption (fasttop): 0x0804d008 ***

但是,当从析构函数中删除DELETE[]时,程序可以正常运行。

这是什么原因造成的?我们非常感谢您的帮助。

推荐答案

问题是您在对象中动态分配内存,而不是声明复制构造函数/赋值运算符。当您分配内存并负责删除它时,您需要定义编译器生成的所有四个方法。

class XSample
{
    public:
        // Pointer inside a class.
        // This is dangerous and usually wrong.
        Uint16 *Beat;
};

XSample::XSample(Uint16 NewBeats,Uint16 NewBPM,Uint8 NewRepeat)
{
    // You allocated it here.
    // But what happens when you copy this object or assign it to another variable.
    Beat = new Uint16[NewBeats];
}

XSample::~XSample()
{
    // Delete here. Turns into double delete if you don't have
    // copy constructor or assignment operator.
    delete [] Beat;
}

执行此操作时,上述内容会发生什么情况:

XSample   a(15,2,2);
XSample   b(a);  // Copy constructor called.
XSample   c(15,2,2);

c = a; // Assignment operator called.

解决此问题的两种方法:

  1. 创建复制构造函数/赋值运算符。
  2. 使用为您执行内存管理的其他对象。

我会使用解决方案2(因为它更简单)。
这也是一个更好的设计。内存管理应该由他们自己的类来完成,您应该集中精力在您的鼓上。

class XSample
{
  public:
    std::vector<Uint16> Beat;
};

XSample::XSample(Uint16 NewBeats,Uint16 NewBPM,Uint8 NewRepeat):
        Beat(NewBeats)
{
         // Notice the vector is constructed above in the initializer list.
}

    // Don't need this now.
XSample::~XSample()
{
}

如果您想用硬方法:
Dynamically allocating an array of objects

如果您想在此处查看编译器版本:
C++ implicit copy constructor for a class that contains other objects

这篇关于向向量添加时析构函数内部的双重释放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆