Потеря памяти при многомерном массиве динамиков c - PullRequest
0 голосов
/ 01 марта 2020

У меня есть класс "Список", который является просто динамическим c массивом, созданным с помощью шаблонов. В моей задаче мне нужно иметь список строк, все идет хорошо и работает, но в нем течет память. У меня также есть список сущностей в моем коде, но его память освобождается, если я правильно понимаю, что говорит valgrind. Я думаю, что проблема в многомерности. Я даже не понимаю, почему это происходит, но я не знаю, как это исправить.

список

#ifndef ____LIST__HJKIPU13

#define ____LIST__HJKIPU13

#define I_CAP 8

#include <iostream>

using namespace std;

template <typename T>

class List {
    T *_array;
    int _capacity;
    int _size;

public:

    List ()
    {
        _array = new T[I_CAP];
        if (_array == nullptr) {
            cerr << "Error, in constructor (dynamic_array.cpp, line 8)";
            exit(1);
        }
        _capacity = I_CAP;
        _size = 0;
    }

    List (const List &other)
    {
        _array = new T[other._capacity];
        if (_array == nullptr) {
            cerr << "Error, in copy constructor (dynamic_array.cpp, line 8)";
            exit(1);
        }
        _capacity = other._capacity;
        _size = other._size;
        copy(other._array, other._array+other._size, _array);
    }

    ~List () {delete[] _array;}

    //--------------------------------------------------------------------------------

    int size () {return _size;}

    void resize (int newSize)
    {
        T *temp = new T[newSize];
        if (temp == NULL) {
            cerr << "Error, in function resize (dynamic_array.cpp, line 27)";
            exit(1);
        }
        std::copy(_array, _array+_capacity, temp);
        delete[] _array;
        _array = temp;
        _capacity = newSize;
    }

    //--------------------------------------------------------------------------------

    T &at (int index)
    {
        if (_size <= index) {
            cerr << "Error, in function get (BList.cpp, line 22)";
            exit(1);
        }
        return _array[index];
    }

    T &operator[] (int index) {return at(index);}

    void insert (int index, T &data)
    {
        if (index > _size) {
            cerr << "Error, in function insert (list.cpp, line 40)";
            exit(1);
        }
        if (isFull()) {
            resize(_capacity*2);
        }

        shitright(index);
        _array[index] = data;
        _size++;
    }

    void removeAt (int index)
    {
        if (index >= _size) {
            cerr << "Error, in function removeAt (list.cpp, line 55)";
            exit(1);
        }
        shitleft(index);
        _size--;
    }

    //--------------------------------------------------------------------------------

    void add (T &data)
    {
        if (isFull()) {
            resize(_capacity*2);
        }

        _array[_size] = data;
        _size++;
    }

    void remove (T &data)
    {
        int index = indexOf(data);
        if (index == -1) {
            std::cerr << "Error " << endl;
            exit(1);
        }

        removeAt(index);
    }

    int  indexOf (T &data)
    {
        int index = -1;

        for (int i = 0; i < _size; i++) {
            if (_array[i] == data) {index = i; break;}
        }

        return index;
    }

    bool contains (T &data)
    {
        if (indexOf(data) == -1) return false;
        else return true;
    }

    //--------------------------------------------------------------------------------

    bool isEmpty () {return static_cast<bool>(_size);}

    void clear () {_size = 0;}

    bool isFull () {return _size == _capacity;}

    //--------------------------------------------------------------------------------

    T shitleft(int index)
    {
        if (index >= _capacity || _size >= _capacity || _size <= index) {
            cerr << "Error, in function shiftleft (dynamic_array.cpp, line 51)";
            exit(1);
        }
        T temp = _array[index];
        for (int i = index; i < _size-1; i++) {
            _array[i] = _array[i+1];
        }

        return temp;
    }

    void shitright(int index)
    {
        if (index >= _capacity || _size >= _capacity || _size <= index) {
            cerr << "Error, in function shiftright (dynamic_array.cpp, line 65)";
            exit(1);
        }

        if (isFull) resize(_capacity*2);

        for (int i = _size; i > index; i--) {
            _array[i] = _array[i-1];
        }
    }

    //

    friend ostream &operator<< (ostream &stream, List<T> &list)
    {
        for (int i = 0; i < list._size; i++) {
            stream << i << ":  <={ " << list._array[i] << " }=>  ";
        }
        if (list._size == 0) stream << ": {empty}" << endl;
        return stream;
    }
};

#endif

пример использования

void entitytoTable (List<List<string>> &list, List<Book> &bookList)
{
    for (int i = 0; i < bookList.size(); i++) {
        string temp;
        List<string> *l = new List<string>;
        temp = to_string(bookList[i].id);
        (*l).add(temp);
        temp = bookList[i].title;
        (*l).add(temp);
        temp = to_string(bookList[i].pages);
        (*l).add(temp);
        temp = to_string(bookList[i].price);
        (*l).add(temp);
        temp = to_string(bookList[i].nChar);
        (*l).add(temp);
        list.add(*l);
    }
}

1 Ответ

1 голос
/ 01 марта 2020

Вы теряете все ассигнования из

List<string> *l = new List<string>;

, потому что вы никогда не звоните delete на l. Не используйте new здесь вообще. Просто объявите List<string> как автоматическую c переменную:

List<string> l;

Тогда ваш класс также нарушает правило 0/3/5 , поскольку оно не определяет оператор присвоения копии.


Проверка if (_array == nullptr) после _array = new T[I_CAP]; не имеет смысла. Если распределение завершится неудачно, new сгенерирует исключение, а если оно не сработает, оно никогда не вернет nullptr.

То же самое относится к T *temp = new T[newSize]; if (temp == NULL) в resize.


Могут быть и другие проблемы.

...