数组删除导致EXC_BAD_ACCESS错误

时间:2012-01-24 17:28:32

标签: 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)
{
    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来自哪里。

我意识到代码非常不完整,但我真的不知道现在哪里开始寻找bug,并且想知道哪些可能的条件会导致delete[]错误。

修改

添加了c'tor,d'tor和赋值运算符。我远离PC,因此代码可能不是100%准确。将值赋给fooArray并访问它们的工作正常。

另外,我非常感谢可能导致delete[]抛出错误的一般问题列表,这样我至少可以知道在哪里查看代码。

编辑2

所以我遵循Xeo的建议使用std::uninitialized_copy,现在代码工作正常并在g ++下编译。析构函数也可以在Visual Studio中正常工作,但以某种方式删除someOtherFooFuncion中的fooArray会使其崩溃。

还有其他想法吗?

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

不要在C ++中使用memcpy

我不能强调这一点。当{C}中的memcpy类对象(确切地说是非POD)时,你打破了由其构造函数定义的那个类'不变量,因为你正在规避那些。每次memcpy一个std::string类时,您都会获得一个新对象,将相同内存作为另一个对象。你会得到一个双重删除,这会导致你的崩溃。

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

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

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

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