添加到向量时在析构函数内部进行双重释放
嘿,我正在使用鼓机,并且遇到矢量问题。
每个序列都有一个样本列表,并且样本在向量中排序。然而,当样本在向量上被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 [] 时,程序完美运行。
是什么原因造成的?非常感谢任何帮助。
Hey, I am working on a drum machine, and am having problems with vectors.
Each Sequence has a list of samples, and the samples are ordered in a vector. However, when a sample is push_back on the vector, the sample's destructor is called, and results in a double free error.
Here is the Sample creation code:
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;
}
And the 'Dynamo' code that creates each sample in the vector:
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));
}
Here is main():
int main()
{
XDynamo Dynamo;
Dynamo.CreateSample(4,120,2);
Dynamo.CreateSample(8,240,1);
return 0;
}
And this is what happens when the program is run:
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 ***
However, when the delete [] is removed from the destructor, the program runs perfectly.
What is causing this? Any help is greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您需要一个适当的复制构造函数和赋值运算符,因为您有一个不平凡的析构函数(更准确地说,因为您的类包装了内存分配)。请参阅“三巨头规则”:
更新:
正如 Martin York 在评论中提到的,这个答案实际上只是解决了问题的直接原因,但并没有真正提出解决问题的最佳方法。修复它,即使用自动管理资源的 RAII 类成员。从表面上看(给定示例代码),
Beat
成员可能是std::vector
而不是指向手动分配数组的指针。vector<>
成员将允许类不需要特殊的 dtor、copy ctor 或赋值运算符 - 所有这些部分都将自动提供给Beat
成员(如果它)是一个向量
。You need a proper copy constructor and assignment operator since you have a non-trivial destructor (more accurately because your class wraps a memory allocation). See the 'Rule of the Big 3':
Update:
As Martin York mentioned in the comments, this answer really just addresses the immediate cause of the problem but doesn't really suggest the best way to fix it, which is to use RAII class members that manage the resources automatically. On the face of it (given the example code), the
Beat
member might be astd::vector<>
instead of a pointer to a manually allocated array. Avector<>
member would allow the class to not need a special dtor, copy ctor or assignment operator - all those pieces would be automatically provided for theBeat
member if it were avector<>
.问题是您在对象中动态分配内存,但没有声明复制构造函数/赋值运算符。当您分配内存并负责删除它时,您需要定义编译器生成的所有四个方法。
当你这样做时,上面会发生什么:
解决这个问题的两种方法:
我会使用解决方案 2(因为它更简单)。
这也是一个更好的设计。内存管理应该由他们自己的类来完成,你应该专注于你的鼓。
如果您想以困难的方式做到这一点:
动态分配对象数组
如果你想在这里查看编译器版本:
包含 other 的类的 C++ 隐式复制构造函数对象
The problem is you are dynamically allocating memory in your object but not declaring a copy constructor/ assignment operator. When you allocate memory and are responsible for deleting it you need to define all FOUR methods that the compiler generates.
What happens to the above when you do:
Two ways to solve this:
I would use solution 2 (as it is simpler).
Its also a better design. Memory management should be done by their own class and you should concentreate on your drums.
If you want to do it the hard way:
Dynamically allocating an array of objects
If you want to see what the compiler versions look here:
C++ implicit copy constructor for a class that contains other objects
编译器添加了一个默认的复制构造函数,这意味着
XSample::Beats
在samples.push_back(...)
期间获得了别名。您应该添加一个正确初始化 XSample 的复制构造函数,可能是通过从参数复制XSample::Beats
来实现的。The compiler added a default copy constructor which means that
XSample::Beats
got aliased duringsamples.push_back(...)
. You should add a copy constructor that initializes XSample correctly, probably by copyingXSample::Beats
from the argument.Vector 正在复制构造您的
XSample
(使用编译器生成的默认复制构造函数),因此在破坏副本时会导致问题。您可以在向量中存储指向XSample
的指针或编写适当的复制构造函数。vector is copy-constructing your
XSample
s (using the compiler generated default copy constructor), and as a result, causing problems when it destructs the copy. You can store pointers toXSample
in the vector or write a proper copy constructor.发生的情况是
Samples.push_back()
将其参数复制到向量中。由于XSample
没有定义复制构造函数,因此编译器会创建一个默认构造函数,该构造函数执行浅复制。这意味着向量中原始和副本中的Beat
指针都指向同一内存。然后,原始内容在push_back()
末尾被破坏,删除Beat
指针。在 main 的末尾,
Dynamo
被析构,调用每个元素的析构函数。这会尝试删除已删除的Beat
指针,从而导致双重删除错误。What is happening is that
Samples.push_back()
copies its argument into the vector. SinceXSample
doesn't have a copy constructor defined, the compiler creates a default constructor, which does a shallow copy. This means that theBeat
pointer in both the original and the copy in the vector point to the same memory. The original is then destructed at the endpush_back()
, deleting theBeat
pointer.At the end of main,
Dynamo
is destructed, calling the destructor of each of the elements. This tries to delete the already deletedBeat
pointer, resulting in your double delete error.