嘿,我在一个鼓机上工作,我遇到了矢量的问题。
每个序列都有一个样本列表,这些样本在一个向量中排序。但是,当样本在向量上为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\n");
Beat = new Uint16[Beats];
}
XSample::~XSample()
{
printf("XSample Destruction\n");
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 []时,程序可以正常运行。
是什么导致了这种情况?任何帮助都是非常感谢的。
发布于 2010-05-12 06:32:33
问题是您在对象中动态分配内存,而不是声明一个复制构造函数/赋值操作符。当您分配内存并负责删除它时,您需要定义编译器生成的所有四个方法。
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.有两种方法可以解决这个问题:
我会使用解决方案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
发布于 2010-05-12 04:00:55
你需要一个合适的复制构造函数和赋值操作符,因为你有一个非平凡的析构函数(更准确地说,因为你的类包装了一个内存分配)。请看“三大法则”:
更新:
正如Martin York在评论中提到的,这个答案实际上只是解决了问题的直接原因,但并没有真正提出解决问题的最佳方法,即使用自动管理资源的RAII类成员。从表面上看(给定示例代码),Beat成员可能是一个std::vector<>,而不是指向手动分配的数组的指针。vector<>成员将允许类不需要特殊的dtor、copy ctor或赋值操作符-如果Beat成员是vector<>,那么所有这些部分都将自动提供给它。
发布于 2010-05-12 04:00:41
编译器添加了一个默认的复制构造函数,这意味着在samples.push_back(...)期间XSample::Beats会出现别名。您应该添加一个复制构造函数来正确初始化XSample,方法可能是从参数中复制XSample::Beats。
https://stackoverflow.com/questions/2814013
复制相似问题