2012-01-24 38 views
1

我有這樣定義的類Foo刪除陣列給EXC_BAD_ACCESS錯誤

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,德TOR和賦值運算符。我遠離PC,因此代碼可能不是100%準確的。賦值給fooArray並訪問它們雖然工作得很好。

此外,我將非常感謝可能會導致delete[]拋出錯誤的問題的一般列表,以便我至少可以瞭解在代碼中查找的位置。

編輯2

所以我也跟着XEO的建議使用std::uninitialized_copy,現在的代碼工作正常,在G ++編譯。析構函數也可以在Visual Studio中正常工作,但不知怎的,刪除someOtherFooFuncion中的fooArray會使其崩潰。

還有其他想法嗎?

+0

你有一個默認的構造函數嗎?如果是這樣,你可以發佈它嗎? – hmjd

+0

你記得[規則三](http://stackoverflow.com/questions/4172722)嗎?爲什麼你不使用'std :: vector'? –

+0

@MikeSeymour我有一個ctor和賦值運算符和dtor,但不能使用矢量因爲它是一個類賦值 – wrongusername

回答

1

不要在C++中使用memcpy

我不能強調這一點。當在C++中使用類對象(確切地說非POD)時,由於您正在規避那些類,因此您打破該類'不變量由其構造函數定義。每當你 a 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/assignment操作符。

+0

嘿,非常感謝答案!我會盡快嘗試。不幸的是,儘可能多地使用向量,這是一個明確需要動態數組的類賦值:( – wrongusername

+0

它工作!至少在g ++中。嘗試運行我的代碼,但:( – wrongusername

+0

@wrongusername:沒有更多的代碼,這將很難找出究竟出了什麼問題,請創建一個[SSCCE](http://sscce.org),以便我們可以進一步調查。 – Xeo

2

確保您定義了複製構造函數和賦值運算符。他們需要fooArray分配內存。如果您沒有定義副本和operator=,編譯器會爲您生成它們。但是,編譯器生成的將只複製fooArray指針,可能導致雙重deletes

如果您已經定義了它們,請將相關的代碼添加到您的問題中。

編輯:我可以看到您的副本構造函數沒有分配內存,並且您的賦值運算符正在使用memcpy()。兩者都可能導致問題。

+0

我已經定義了複製構造函數和作業運算符,他們似乎工作找到,因爲我寫他們在內存中,我會盡快添加代碼 – wrongusername

1

如果您定義了一個默認構造函數,則必須將fooArray初始化爲NULL,否則fooArray可能指向一個隨機內存位置,然後該位置將受到delete[]的限制。

+0

hm我初始化一個動態數組而不是空值,認爲它也可以工作 – wrongusername