C++ 数组删除导致EXC\u错误\u访问错误
我有一个类Foo定义如下:C++ 数组删除导致EXC\u错误\u访问错误,c++,arrays,delete-operator,C++,Arrays,Delete Operator,我有一个类Foo定义如下: class Foo { public: Foo(int num); Foo(const Foo& other); ~Foo(); Foo& operator=(const Foo& other); ... private: string *fooArray; void clearMemory(); ... } Foo::Foo(int num) { fooAr
class Foo
{
public:
Foo(int num);
Foo(const Foo& other);
~Foo();
Foo& operator=(const Foo& other);
...
private:
string *fooArray;
void clearMemory();
...
}
Foo::Foo(int num)
{
fooArray = new string[num];
}
Foo::Foo(const Foo& other)
{
*this = other;
}
Foo::~Foo()
{
clearMemory();
}
Foo& operator=(const Foo& other)
{
clearMemory();
fooArray = new string[other.size]; // size is a private variable
memcpy(fooArray, other.fooArray, other.size * sizeof(string));
}
void Foo::someOtherFooFuncion(int newNum)
{
clearMemory(); // crash with Visual Studio, does not crash with g++, but g++ also
// crashes when destructor is called
fooArray = new string[newNum];
}
void Foo::clearMemory()
{
if(fooArray != NULL)
{
delete[] fooArray; // sometimes it crashes here with g++; it always crashes when
// compiling in Visual Studio
fooArray = NULL;
}
}
// src_begin src_end dest
std::uninitialized_copy(other.array, other.array + other.size, array);
正如代码注释中所指出的,它有时会让我崩溃。我已经试着遵循GDB中的步骤,我已经做到了
destructing Foo:
@0x7fff5fbff9b0
$26 = {
fooArray = 0x1001009d8,
...
}
然后到达delete[]fooArray,突然
Foo(49858) malloc: *** error for object 0x100100990: pointer being freed was not allocated
我不知道0x100990是从哪里来的
我意识到代码非常不完整,但我现在真的不知道从哪里开始查找错误,我想了解一些可能导致delete[]错误的提示
编辑:
添加了c'tor、d'tor和赋值运算符。我远离电脑,所以代码可能不是100%准确。不过,将值赋给fooArray并访问它们效果很好
另外,我非常希望能够提供一个可能导致delete[]抛出错误的问题的一般列表,这样我至少可以知道在代码中查找的位置
编辑2:
所以我按照Xeo的建议使用std::uninitialized_copy,现在代码运行良好,可以在g++下编译。析构函数在VisualStudio中也可以很好地工作,但是在其他FooFunction中删除fooArray会导致崩溃
还有其他想法吗 确保定义了复制构造函数和赋值运算符。他们需要为fooArray分配内存。如果您没有定义copyctor和operator=,编译器将为您生成它们。但是,编译器生成的指针只会复制fooArray指针,这可能会导致双重删除 如果您已经定义了它们,请在问题中添加相关代码
编辑:我可以看到复制构造函数没有分配内存,赋值操作符使用的是memcpy。两者都可能导致问题。请确保定义了复制构造函数和赋值运算符。他们需要为fooArray分配内存。如果您没有定义copyctor和operator=,编译器将为您生成它们。但是,编译器生成的指针只会复制fooArray指针,这可能会导致双重删除 如果您已经定义了它们,请在问题中添加相关代码
编辑:我可以看到复制构造函数没有分配内存,赋值操作符使用的是memcpy。两者都可能导致问题。如果定义默认构造函数,则必须将fooArray初始化为NULL,否则fooArray可能指向随机内存位置,该位置随后会被删除[]。如果定义默认构造函数,则必须将fooArray初始化为NULL,否则,FoeSoad可能指向一个随机内存位置,然后在DECK[].</P>中使用McCPy不使用C++。 这一点我怎么强调都不过分。当C++中的一个类对象精确地被定义时,你就破坏了它的构造函数定义的类不变量,因为你正绕过那些构造函数。每次您memcpya一个std::string类时,您都会得到一个新对象,该对象与另一个对象引用相同的内存。您将得到双重删除,这将导致您的崩溃 使用std::uninitialized_copy from,如下所示:
class Foo
{
public:
Foo(int num);
Foo(const Foo& other);
~Foo();
Foo& operator=(const Foo& other);
...
private:
string *fooArray;
void clearMemory();
...
}
Foo::Foo(int num)
{
fooArray = new string[num];
}
Foo::Foo(const Foo& other)
{
*this = other;
}
Foo::~Foo()
{
clearMemory();
}
Foo& operator=(const Foo& other)
{
clearMemory();
fooArray = new string[other.size]; // size is a private variable
memcpy(fooArray, other.fooArray, other.size * sizeof(string));
}
void Foo::someOtherFooFuncion(int newNum)
{
clearMemory(); // crash with Visual Studio, does not crash with g++, but g++ also
// crashes when destructor is called
fooArray = new string[newNum];
}
void Foo::clearMemory()
{
if(fooArray != NULL)
{
delete[] fooArray; // sometimes it crashes here with g++; it always crashes when
// compiling in Visual Studio
fooArray = NULL;
}
}
// src_begin src_end dest
std::uninitialized_copy(other.array, other.array + other.size, array);
未经测试,因为我是用iPod写的
或者更好,只需使用std::vector而不是原始内存。您将不再需要析构函数和复制cto/赋值操作符。在C++中不使用MeMCPY
这一点我怎么强调都不过分。当C++中的一个类对象精确地被定义时,你就破坏了它的构造函数定义的类不变量,因为你正绕过那些构造函数。每次您memcpya一个std::string类时,您都会得到一个新对象,该对象与另一个对象引用相同的内存。您将得到双重删除,这将导致您的崩溃
使用std::uninitialized_copy from,如下所示:
class Foo
{
public:
Foo(int num);
Foo(const Foo& other);
~Foo();
Foo& operator=(const Foo& other);
...
private:
string *fooArray;
void clearMemory();
...
}
Foo::Foo(int num)
{
fooArray = new string[num];
}
Foo::Foo(const Foo& other)
{
*this = other;
}
Foo::~Foo()
{
clearMemory();
}
Foo& operator=(const Foo& other)
{
clearMemory();
fooArray = new string[other.size]; // size is a private variable
memcpy(fooArray, other.fooArray, other.size * sizeof(string));
}
void Foo::someOtherFooFuncion(int newNum)
{
clearMemory(); // crash with Visual Studio, does not crash with g++, but g++ also
// crashes when destructor is called
fooArray = new string[newNum];
}
void Foo::clearMemory()
{
if(fooArray != NULL)
{
delete[] fooArray; // sometimes it crashes here with g++; it always crashes when
// compiling in Visual Studio
fooArray = NULL;
}
}
// src_begin src_end dest
std::uninitialized_copy(other.array, other.array + other.size, array);
未经测试,因为我是用iPod写的
或者更好,只需使用std::vector而不是原始内存。您不再需要析构函数和复制构造函数/赋值运算符。您有默认构造函数吗?如果是的话,你能把它贴出来吗?你还记得那封信吗?为什么不使用std::vector?@MikeSeymour我有一个ctor和赋值运算符以及dtor,但不能使用vector,因为它是一个类赋值。这段代码在很多级别上都是错误的。。真的,请放弃类赋值并使用std::vector。。。或至少报废内存..:你有默认的构造函数吗?如果是的话,你能把它贴出来吗?你还记得那封信吗?为什么不使用std::vector?@MikeSeymour我有一个ctor和赋值运算符以及dtor,但不能使用vector,因为它是一个类赋值。这段代码在很多级别上都是错误的。。真的,请放弃类赋值并使用std::vector。。。或至少报废内存..:我已经定义了复制构造函数和赋值操作符,它们似乎可以找到,因为我在内存中写入它们。我将很快添加代码。我已经定义了复制构造函数和赋值运算符,a
他们似乎找到了工作,因为我在记忆中给他们写信。我将很快添加代码。嗯,我初始化了一个动态数组而不是NULL,我想它会工作得很好。嗯,我初始化了一个动态数组而不是NULL,我想它会工作得很好。嘿,非常感谢你的回答!我很快就会试试的。不幸的是,尽管我很想使用向量,但这是一个明确需要动态数组的类赋值:它起作用了!至少在g++中。当我试图运行我的代码时,Visual Studio仍然崩溃,但是:@ErrorUserName:如果没有更多的代码,将很难找出到底哪里出了问题。请创建一个,这样我们可以进一步调查。嘿,非常感谢你的回答!我很快就会试试的。不幸的是,尽管我很想使用向量,但这是一个明确需要动态数组的类赋值:它起作用了!至少在g++中。当我试图运行我的代码时,Visual Studio仍然崩溃,但是:@ErrorUserName:如果没有更多的代码,将很难找出到底哪里出了问题。请创建一个,以便我们可以进一步调查。