数组删除导致EXC_BAD_ACCESS错误

Array deletion giving EXC_BAD_ACCESS error

本文关键字:BAD 错误 ACCESS EXC 删除 数组      更新时间:2023-10-16

我有一个类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)
{
    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;
    }
}

正如代码注释中所指出的,它有时会让我崩溃。我已经尝试过遵循GDB中的步骤,我已经达到了

destructing Foo:
@0x7fff5fbff9b0
$26 = {
  fooArray = 0x1001009d8, 
  ...
}

然后达到delete[] fooArray,突然

Foo(49858) malloc: *** error for object 0x100100990: pointer being freed was not allocated

不知道0x100100990是从哪里来的。

我意识到代码非常不完整,但我现在真的不知道从哪里开始寻找错误,我想了解一些可能导致delete[]错误的情况。

编辑

添加了c'tor、d'tor和赋值运算符。我不在电脑上,所以代码可能不是100%准确。不过,将值分配给fooArray并访问它们也很好。

此外,我将非常感谢一个可能导致delete[]抛出错误的问题的一般列表,这样我至少可以知道在代码中的位置。

编辑2

因此,我遵循Xeo的建议使用std::uninitialized_copy,现在代码运行良好,并在g++下编译。析构函数在VisualStudio中也可以正常工作,但在someOtherFooFuncion中删除fooArray会导致它崩溃。

还有其他想法吗?

确保定义了一个复制构造函数和一个赋值运算符。他们将需要fooArray分配内存。如果您没有定义副本ctor和operator=,编译器将为您生成它们。然而,编译器生成的指针只会复制fooArray指针,可能会导致deletes加倍。

如果您已经在定义它们,请将相关代码添加到您的问题中。

edit:我可以看到您的复制构造函数没有分配内存,而您的赋值运算符正在使用memcpy()。两者都可能造成问题。

不要在C中使用memcpy++

我再怎么强调也不为过。当memcpy在C++中处理类对象(确切地说是非POD)时,您正在破坏由其构造函数定义的类"不变量",因为您正是在绕过这些不变量。每次memcpystd::string类时,都会得到一个新对象,该对象引用与另一个对象相同的内存。你会被双重删除,这会导致你的崩溃。

使用<algorithm>中的std::uninitialized_copy,如下所示:

//                      src_begin             src_end           dest
std::uninitialized_copy(other.array, other.array + other.size, array);

(未经测试,因为我是用iPod写的)

或者更好的是,只需使用std::vector而不是原始内存。您将不再需要析构函数和复制构造函数/赋值运算符。

如果定义默认构造函数,则必须将fooArray初始化为NULL,否则fooArray可能指向一个随机内存位置,该位置将受到delete[]的约束。