2014-12-08 7 views
0

Я студент, поэтому я извиняюсь перед тем, чтобы не использовать правильные протоколы форума. Я искал часы по этой проблеме, ни один из моих одноклассников не может помочь. Мое назначение - создать конструктор копирования, перегруженный оператор присваивания (=) и деструктор («большой три») на C++ для управления массивом в куче. То, что я написал ниже в VS13, приводит к правильному выводу, но я получаю ошибку отладки: HEAP CORRUPTION DETECTED: C++ crt обнаружил, что приложение записано в память после окончания кучного буфера Может ли кто-нибудь дать мне некоторое руководство по этому поводу, я даже не знать, где искать. Благодаря!!Ошибка копирования кучи с помощью конструктора копирования и перегруженного оператора присваивания

//copy constructor 

myList::myList(const myList& source){ 
cout << "Invoking copy constructor." << endl; 
array_capacity = source.array_capacity; //shallow copy 
elements = source.elements; //shallow copy 
delete[] arrayPointer; 
arrayPointer = new double(source.array_capacity); //deep copy 

for (int i = 0; i < array_capacity; i++) //copy array contents 
    { 
     arrayPointer[i] = source.arrayPointer[i]; 
    } 
} 

//overloaded assignment operator 
myList& myList::operator=(const myList& source){ 

cout << "Invoking overloaded assignment." << endl; 

if (this != &source){ 

array_capacity = source.array_capacity; //shallow copy 

elements = source.elements; //shallow copy 

delete[] arrayPointer; //delete original array from heap 

arrayPointer = new double(array_capacity); //deep copy 

for (int i = 0; i < source.array_capacity; i++) {//copy array contents 
    arrayPointer[i] = source.arrayPointer[i]; 
     } 
    } 
return *this; 
} 

//destructor 
myList::~myList(){ 

cout << "Destructor invoked."<< endl; 

delete[] arrayPointer; // When done, free memory pointed to by myPointer. 

arrayPointer = NULL; // Clear myPointer to prevent using invalid memory reference. 
} 

ответ

2

Есть пара проблем с вашим кодом. Сначала вы вызываете delete по адресу arrayPointer, но он не был инициализирован ничем. Фактически это может привести к удалению памяти, которую вы уже выделили, или привести к исключению или активу при реализации delete. Во-вторых, когда вы инициализируете его, вы назначаете один double, инициализированный значением source.array_capacity. Обратите внимание на скобки, используемые в приведенной ниже строке.

arrayPointer = new double(source.array_capacity); 

Это, безусловно, приведет к непредсказуемому поведению во время копирования, как вы в конечном итоге доступ к элементам вне границ массива. Выше линия присутствует как в вашей копии конструктора и копирования оператора присваивания и должны использовать квадратные скобки вместо так:

arrayPointer = new double[source.array_capacity]; 

Вы также никогда не проверить, есть ли какие-либо элементы, хранящиеся в source экземпляре myList , В этом случае вам, вероятно, следует присвоить nullptr (или NULL в C++ 03) до arrayPointer.

В качестве дополнительной заметки вам не нужно назначать NULLarrayPointer в вашем деструкторе. Как только объект будет уничтожен, он исчезнет, ​​и любая попытка получить к нему доступ после факта приведет к неопределенному поведению в любом случае.

+0

Ваши предложения работали! Вы спасатель жизни, спасибо! Должен ли я отмечать этот пост как «ответил»? как это сделать? –

+0

Да, если ответ решает вашу проблему, вы должны пометить его как принятый, установив флажок в верхней левой части ответа. Если вам полезен более одного ответа, вам решать, какой из них заслуживает принятия. Вы также можете отменить ответы, если вам нравится давать вкладчику небольшой бонус. –

1

Капитан Obvlious указал на проблему в вашем конструкторе копирования.

Вы заметили, что копировальный конструктор и оператор присваивания содержат много одинакового кода, но с тонкой разницей. На самом деле это, вероятно, то, как вы закончили с ошибкой (оператору присваивания должно быть delete[] старое значение, но копировальный конструктор этого не делает.

Копирование дубликатов плохо, потому что это приводит к таким тонким ошибкам, как эта ползучесть . хороший шаблон, который вы можете использовать здесь, что называется copy and swap idiom.

суть в том, что вы определяете копию-конструктор, и вы также определяете swap. После этого вы получите задание бесплатно. Это работает, потому что swap проще реализовать корректно, чем оператор присваивания, и еще одно главное преимущество в том, что ничто не может пойти не так (вам не нужно беспокоиться об ошибках из-за памяти и т. д.).

В вашем коде; сохраняя фиксированную копию-конструктор, вы могли бы добавить в определение класса:

friend void swap(myList &a, myList &b) 
{ 
    std::swap(a.array_capacity, b.array_capacity); 
    std::swap(a.arrayPointer, b.arrayPointer); 
    std::swap(a.elements, b.elements); 
} 

и теперь оператор присваивания очень прост:

myList& myList::operator=(const myList &source) 
{ 
    myList temp(source); 
    swap(*this, temp); 
    return *this; 
} 

старой ресурсы из текущего объекта удаляются с помощью деструктора от temp. Эта версия даже не требует проверки на самоопределение, потому что std::swap(x, x) четко определен.

Это можно даже оптимизировать, приняв source по значению вместо ссылки, как описано на связанной странице.

Смежные вопросы