ошибка в деструкторе класса - PullRequest
3 голосов
/ 03 декабря 2010

Я только начал свой контейнерный класс, и у меня уже есть проблемы:

class Container
{
    private:

    string* BasePointer; // The starting pointer.
    unsigned int Capacity; // The number of values the container can hold.

    public:

    Container() // Default constructor.
    {
        Capacity = 1;
        BasePointer = new string[Capacity];
    }

    ~Container() // Destructor.
    {
        delete BasePointer; // Delete the container to prevent memory leaking.
    }
};

Я получаю ошибку Container Classes(26467) malloc: *** error for object 0x100100088: pointer being freed was not allocated. Что я делаю неправильно?

Ответы [ 5 ]

7 голосов
/ 03 декабря 2010

XXX ptr = new XXX[size] должен соответствовать версии массива delete [] ptr, а не только обычному delete.

Прочтите о бесплатном управлении магазином в C ++, и, как напоминает нам Джеймс, - следуйте правилу о трех в подобных случаях.

4 голосов
/ 03 декабря 2010

Вы должны использовать delete []

delete[] BasePointer;
2 голосов
/ 03 декабря 2010

Другие отметили, что вы не сопоставили new[] с delete, и вы должны изменить delete на delete[], чтобы исправить это. Однако это только первая из ваших проблем.

Вам также необходимо реализовать (или, по крайней мере, объявить как закрытый) конструктор копирования и оператор присваивания копии. В противном случае подумайте о том, что происходит, когда вы делаете это:

{
    Container c1;
    Container c2(c1);
}   // c2.~Container(); // frees the memory pointed to by 'BasePointer'
    // c1.~Container(); // also frees the memory pointed to by 'BasePointer'.

Так как BasePointer член как c1, так и c2 указывает на один и тот же массив, он освобождается дважды.

Есть несколько более простых в использовании альтернатив:

  • Подумайте об использовании std::vector везде, где вы могли бы использовать динамически распределенный массив. Поскольку ваш класс называется Container, я предполагаю, что вы пытаетесь реализовать контейнер, владеющий ресурсами, поэтому, возможно, вы не захотите его использовать.

  • Попробуйте использовать boost::scoped_ptr или std::unique_ptr (если ваш компилятор поддерживает это) для управления владением указателем. Оба они подавляют генерацию неявно объявленного конструктора копирования, заставляя вас реализовать свой собственный, если вы на самом деле пытаетесь их использовать.

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

Наконец, в качестве стилистической точки, вам не нужно использовать malloc для контейнера. Стандартная библиотека предоставляет std::allocator, который можно использовать для выделения пространства и создания объектов.

1 голос
/ 03 декабря 2010

Привет, если вы создаете массив, вы должны использовать delete [] BasePointer;

0 голосов
/ 03 декабря 2010

Чтобы быть более явным, чем другие - когда вы new указали тип массива, вам нужно удалить указатель, используя delete[].

Это происходит не только при использовании new T[size], рассмотрим следующий пример:

typedef int T[42];
int* x = new T;
delete[] x; // needs delete[] though you used new without []

В общем, если ваш объект "владеет" объектом, который он удерживает с помощью указателя, вам следует рассмотреть возможность использования для этого умного указателя (например, boost :: scoped_array). Таким образом, вам не нужно беспокоиться о деконструкции, что происходит, когда генерируется исключение, реализуя оператор присваивания и конструктор копирования ...

...