当我用Xcode编译并运行这个时,我得到错误,至少连续100次,malloc: *** error for object 0x100180: double free
,调试器指向line C
。奇怪的是,在我从中提取的代码中,发生了完全相同的错误,但调试器指向等同于line B
的错误。我试过了,但无法复制。
如果我删除line A
,代码可以工作,但是我得到一个主要的内存泄漏,在大约1分钟内使程序崩溃。删除line C
可以解决问题,但不是一个有效的解决方案,因为a_class
没有适当的析构函数。
#include <iostream>
#include <vector>
struct a_struct
{
int* dynamic_array;
a_struct(int length) {dynamic_array = new int [length];}
a_struct() : dynamic_array(NULL) {}
~a_struct() { if (dynamic_array != NULL) {delete [] dynamic_array;} } //Line A
};
class a_class
{
public:
a_struct* the_structs;
a_class() {Init();}
a_class(a_class const & origin) {Init();}
void Init(){
the_structs = new a_struct [10]; //Line B
for(int q=0; q<10; q++)
the_structs[q] = a_struct(7);}
~a_class() { if (the_structs != NULL) {delete [] the_structs;} } //Line C
};
int main ()
{
std::vector <a_class> the_objects;
for(int q=0; q<10; q++)
the_objects.push_back(a_class());
while(1)
for(int q=0; q <10; q++)
for(int w=0; w <10; w++)
the_objects[q].the_structs[w] = a_struct(7);
}
修复a_struct和a_class具有正确的复制构造函数和赋值操作符。如果还是有问题,再来找我。
确保你所有的课都遵循3的规则。我最近好像经常链接到那个页面。
问题是你试图做你自己的内存管理。
使用内置容器:
struct a_struct
{
std::vector<int> dynamic_array;
a_struct(int length) : dynamic_array(length){}
a_struct() : dynamic_array() {}
};
class a_class
{
public:
std::vector<a_struct> the_structs;
a_class() {Init();}
a_class(a_class const & origin) {Init();}
void Init()
{
the_structs.resize(10);
for(int q=0; q<10; q++)
the_structs[q] = a_struct(7);
}
};
问题是a_struct
没有正确的复制构造函数和operator =
。由于这个原因,两个a_struct::dynamic_array
同时指向相同的内存位置,并且都将在析构函数中调用delete[] dynamic_array;
。因此,double delete。
总是,记住当你在class
中有一个行指针时,你应该做一个深度复制(你复制指针指向的内容),而不是一个浅复制(只是地址)。
在您的例子中,您可以这样更改定义:
struct a_struct
{
int length_; //<<--- add this for record
int* dynamic_array;
a_struct(int length) : length_(length) {dynamic_array = new int [length_]; }
a_struct() : dynamic_array(NULL) {}
a_struct(const a_struct ©) // <<--- copy ctor
{
do_copy(copy);
}
a_struct& operator = (const a_struct ©) // <<--- assignment operator
{
delete[] dynamic_array; // clear earlier array
do_copy(copy);
return *this;
}
~a_struct() { if (dynamic_array != NULL) {delete [] dynamic_array;} } //Line A
void do_copy (const a_struct ©)
{
// do necessary null checks for "copy"
dynamic_array = new int[length_ = copy.length];
memcpy(dynamic_array, copy.dynamic_array, length_);
}
};
与其他class
相同的预防措施
问题是a_struct
中隐式生成的复制构造函数不进行深度复制,但析构函数总是假设为每个实例分配了内存。您需要为它创建一个执行深度复制的复制构造函数。但更好的是只使用std::vector
而不是new和delete。这样,您就不必担心要记住保持所有构造函数的正确性。
另外,a_class
的复制构造函数实际上并不复制对象。当它不支持预期的复制语义时,这几乎肯定会给您带来问题。