Мой деструктор выдает мне эту ошибку: *** Ошибка в `./main ': двойное освобождение или повреждение (fasttop) :? - PullRequest
0 голосов
/ 26 апреля 2018

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

Оператор присваивания (знак равноОператор присваивания также должен выполнить глубокое копирование объекта аргумента.Он должен возвращать себя (или, что более эффективно, ссылку на себя), чтобы поддерживать несколько назначений в одной строке, например, a = b = c.Если вы сначала реализуете свой оператор присваивания, его можно использовать в конструкторе копирования, но это не является обязательным требованием.

Оператор Is Equals (==).Оператор «is equals» должен возвращать true, если объект аргумента имеет тот же размер, что и принимающий объект, и значения в массивах данных обоих объектов идентичны.

Оператор вставки (<<).Оператор вставки должен добавить параметр int в принимающую IntCollection.Функциональность точно такая же, как и у функции add (), т.е. добавляет целые в коллекцию.Однако обратите внимание, что эта функция должна возвращать ссылку на себя, чтобы поддерживать несколько вставок в одной строке, например, c << 45 << -210.В отличие от оператора присваивания, этот возврат должен быть выполнен по ссылке, потому что каждая вставка фактически изменяет объект IntCollection, а вставка выполняется слева направо.</p>

Деструктор.Функция add () вызывает addCapacity () для выделения памяти, когда ей нужно больше места.Нигде в этой программе память не освобождается с помощью delete [], что означает утечку памяти!Добавьте деструктор, который правильно обрабатывает это.

addCapacity.Обратите внимание, что addCapacity () является закрытой функцией-членом.Что произойдет, если вы попытаетесь вызвать его из-за пределов класса, т. Е. Добавив строку в main () ниже?

c.addCapacity ();

Вот мой код: IntCollection.h:

#ifndef INTCOLLECTION_H
#define INTCOLLECTION_H

// Allocate memory in chunks of ints of this size.
const int CHUNK_SIZE = 5;

class IntCollection
{
  private:
  // The number of ints currently stored in the int
    int size;
  // the total number of elements available for storage
  // in the data array
    int capacity;
  // A pointer to the dynamically allocated data array
    int* data;
  // a private member function to allocate more memory 
  // if necessary
    void addCapacity();
  public:
  // Constructor
    IntCollection();
  // Destructor
    ~IntCollection();
  // Copy constructor:
    IntCollection(const IntCollection &c);

    void add(int value);
    int get(int index);
    int getSize();
    IntCollection& operator=(const IntCollection &c);
    bool operator==(const IntCollection &c);
    IntCollection& operator<<(int value);
};

#endif

IntCollection.cpp:

#include "IntCollection.h"
#include <cstdlib>
#include <iostream>
using namespace std;

IntCollection::IntCollection() 
{
    // Initialize member data to reflect an empty
    // IntCollection
    size = capacity = 0;
    data = NULL;
}

IntCollection::~IntCollection() 
{
    delete [] data;
}

IntCollection::IntCollection(const IntCollection &c) {
    size = c.size;
    capacity = c.capacity;
    data = c.data;

    for (int i = 0; i < c.size; i++) 
    {
        data[i] = c.data[i];
    }
}

void IntCollection::addCapacity() 
{
    // Create a new, bigger buffer, copy the current data to
    // it, delete the old buffer, and point our data
    // pointer to the new buffer
    int *newData;
    data = new int[capacity];
    capacity += CHUNK_SIZE;
    newData = new int[capacity];

    for (int i = 0; i < size; i++) 
    {
        newData[i] = data[i];
        delete[] data;
        data = newData;
    }
}

void IntCollection::add(int value) 
{
    // first, allocate more memory if we need to
    if (size == capacity) 
    {
        addCapacity();
    }
    // Now, add the data to our array and increment size
    data[size++] = value;
}

int IntCollection::get(int index) 
{
    if (index < 0 || index >= size) 
    {
        cout << "ERROR: get() trying to access index out of range.\n";
        exit(1);
    }
    return data[index];
}

int IntCollection::getSize() 
{
    return size;
}

IntCollection &IntCollection::operator=(const IntCollection &c) 
{
    size = c.size;
    capacity = c.capacity;
    data = c.data;

    return *this;
}

bool IntCollection::operator==(const IntCollection &c) 
{
    if ((size == c.size) && (capacity == c.capacity)) 
    {
        for (int m = 0; m < size; m++) 
        {
            if (data[m] == c.data[m]) 
            {
                continue;
            } else 
            {
                return false;
            }
        }
    }
    return true;
}

IntCollection &IntCollection::operator<<(int value) 
{
    add(value);
    return *this;
}

main.cpp:

#include "IntCollection.h"
#include <iostream>
using namespace std;

int main() 
{
  IntCollection c;

  c.add(45);
  c.add(-210);
  c.add(77);
  c.add(2);
  c.add(-21);
  c.add(42);
  c.add(7);

  for (int i = 0; i < c.getSize(); i++)
  {
    cout << c.get(i) << endl;
  }

  IntCollection d(c);
  for (int i = 0; i < c.getSize(); i++)
  {
    cout << c.get(i) << endl;
  }

  IntCollection e;
  e = c;
  cout << "Testing = Overload" << endl;

  for(int i = 0; i < c.getSize(); i++)
  {
    cout << c.get(i) << endl;
  }

  IntCollection f;
  f<<8<<9<<10;
  cout << "Testing<<Overload" << endl;
  for(int i = 0; i < f.getSize(); i++)
  {
    cout << f.get(i) << endl;
  }

  cout << "Testing == Overload" << endl;

  c.add(10);

  if(f == c)
  {
    cout << "Both objects match" << endl;
  }
  else
  {
    cout << "They don't match" << endl;
  }

  return 0;
}

После того, как я поверил, что исправил большинство моих ошибок, я получу это в качестве вывода:

*** Error in `./main': double free or corruption (fasttop): 0x0000000000b2ec80 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x70bfb)[0x7ff7e6f70bfb]
/lib/x86_64-linux-gnu/libc.so.6(+0x76fc6)[0x7ff7e6f76fc6]
/lib/x86_64-linux-gnu/libc.so.6(+0x7780e)[0x7ff7e6f7780e]
./main[0x400fa1]
./main[0x400fe2]
./main[0x400aa2]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7ff7e6f202e1]
./main[0x40097a]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:01 11008976                           /home/runner/main

Я не буду публиковать все это, потому что это долго.Мой деструктор вызывает это?Я не уверен, как это исправить, и я никогда не сталкивался с этой ошибкой раньше.

1 Ответ

0 голосов
/ 26 апреля 2018

Эта строка, из вашего конструктора копирования, является вероятной проблемой:

data = c.data;

После этой строки у вас есть два объекта, указывающих на то же самое данные .Это мелкая копия.

Если один из объектов будет уничтожен, тогда если будут delete[] данные, оставляя другой объект с недопустимым указателем.Когда второй деструктор объектов попытается delete[] данные (снова!), Это приведет к неопределенному поведению .

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

То же самое с оператором копирования-назначения.

...