Помогите решить проблему с утечкой памяти в коде C++
Помогите решить задачу, проверяющая система на засчитывает задание и выдает ошибку Memory leak detected. Не могу понять, где происходит утечка.
Условие
В лекциях мы уже начали реализовывать свой вектор. В этой задаче вам надо его развить: добавить методы Size, Capacity и PushBack. Пришлите на проверку заголовочный файл simple_vector.h, содержащий объявление и определение шаблона класса SimpleVector:
template <typename T>
class SimpleVector {
public:
SimpleVector() = default;
explicit SimpleVector(size_t size);
~SimpleVector();
T& operator[](size_t index);
T* begin();
T* end();
size_t Size() const;
size_t Capacity() const;
void PushBack(const T& value);
private:
...
};
Требования:
- метод
Capacityдолжен возвращать текущую ёмкость вектора — количество элементов, которое помещается в блок памяти, выделенный вектором в данный момент - метод
Sizeдолжен возвращать количество элементов в векторе - метод
PushBackдобавляет новый элемент в конец вектора; если в текущем выделенном блоке памяти не осталось свободного места (т.е.Size() == Capacity()), вектор должен выделить блок размера2 * Capacity(), скопировать в него все элементы и удалить старый. - первый вызов метода PushBack для вновь созданного объекта должен делать ёмкость, равной единице
- метод
PushBackдолжен иметь амортизированную константную сложность методыbeginиendдолжны возвращать итераторы текущие начало и конец вектора - в деструкторе должен освобождаться текущий блок памяти, выделенный вектором
также см. дополнительные требования к работе
SimpleVectorв юнит-тестах в приложенном шаблоне решения
Заготовка решения:
Заготовка .h заголовка: https://d3c33hcgiwev3.cloudfront.net/q-OL4qX_EeilzRLZf2WxfA_ac4e8270a5ff11e89fd0455a8819d387_simple_vector.h?Expires=1595894400&Signature=FJfwZcYJ3BGDSLPvZ-rK0kCjoEIBqVJzttcB2~lB5ktYV66Ne6LRvs272iJGelixzecp1mbwQI62foTVffLgGPqiP0XV8g-t-X-lwHJ--3zPBPrvvAsOR2eOzq2M-AAa7OztFSOyPJGMFWqxSbGvTj5O27T98v7qK0Ic95own84_&Key-Pair-Id=APKAJLTNE6QMUY6HBC5A
Замечание*
Заголовочный файл, который вы пришлёте на проверку, не должен подключать файлы <vector>, <list>, <forward_list>, <deque>, <map>. Если у вас будет подключен один из этих файлов, вы получите ошибку компиляции.
Подсказка
Наверняка в вашей реализации шаблона класса SimpleVector будет поле, являющееся указателем. В конструкторе по умолчанию вам надо будет его чем-нибудь проинициализировать. В лекциях мы рассматривали только один способ инициализации указателей — с помощью оператора new. В C++ есть специальное значение, означающее указатель, который ни на что не указывает — nullptr:
int* p = nullptr;
string* q = nullptr;
map<string, vector<int>>* r = nullptr;
Вы можете использовать nullptr для инициализации указателя в конструкторе по умолчанию.
А вот мое решение:
#pragma once
#include <cstdlib>
using namespace std;
template <typename T>
class SimpleVector {
public:
SimpleVector() {
data = nullptr;
end_ = data;
size_ = 0;
}
explicit SimpleVector(size_t size) {
//data = (T*) calloc (size, sizeof(T)); // выделил память под size элементов и заполнить 0
data = new T[size];
end_ = data + size;
size_ = size;
}
~SimpleVector() {
delete[] data; // освобождается память
}
T& operator[](size_t index) { return data[index]; }
T* begin() const { return data; }
T* end() const { return end_; }
size_t Capacity() const { return end_ - data; }
size_t Size() const { return size_; }
void PushBack(const T& value) {
if (size_ == Capacity()) {
if (size_ == 0) { // для вновь созданного векторы
//data = (T*) calloc (1, sizeof(T)); // выделяю память для одного элемента типа T
data = new T[1];
data[size_] = value;
++size_;
end_ = data + size_;
}
else { // если у вектора кол-во полей > 0
//data = (T*) realloc (data, sizeof(T[2 * Capacity()])); // расширил область памяти оставив прошлые значения
T* local_data = new T[size_];
for (size_t i = 0; i < size_; ++i) {
local_data[i] = data[i];
}
data = new T[2 * Capacity()];
for (size_t i =0; i < size_; ++i) {
data[i] = local_data[i];
}
delete[] local_data;
data[size_] = value;
++size_;
end_ = data + size_ * 2;
}
}
else { // если у вектора уже выделена память под новые поля
data[size_] = value;
size_++;
}
}
private:
T *data;
T *end_;
size_t size_;
};
Собственно у меня проблема в том, что я не могу понять где у меня утечка памяти.
Ответы (1 шт):
data = new T[2 * Capacity()] - Вы до этого забыли про delete[]
(с) Kir_Antipov
Создал прецедент - воспользовался настойчивым разрешением модераторов переносить комментарии в ответ. Более того, я даже указал автора.