Zbyt duże zużycie pamięci

0

Cześć, piszę program na zaliczenie. Jest to kopia klasy vector z niektórymi metodami. Mam jednak problem bo po odpaleniu testów przez prowadzącego wyszło, że zużycie pamięci jest zbyt duże bo wynosi 255mb a powinno być 5mb. Czy mógłby ktoś podpowiedzieć jak podejść do problemu i jak można wykrywać tego typu błędy. Poniże mój kod.

#include "JippVector.h"
#include <new>

using namespace std;

template class JippVector<int>;
template class JippVector<double>;
template class JippVector<string>;
template class JippVector<char>;

template<typename T>
JippVector<T>::JippVector()
{
	i_size = 0;
	i_capacity = 0;
	array = NULL;
}

template<typename T>
JippVector<T>::JippVector(int capacity)
{
	i_size = 0;
	i_capacity = capacity;
	array = new T[i_capacity];
	if (array == nullptr)
	{
		throw bad_alloc();
	}
}

template<typename T>
JippVector<T>::~JippVector()
{
	if (array != NULL)
	{
		delete[] array;
	}
}


template<typename T>
JippVector<T>::JippVector(const JippVector& ob) :
	i_size(ob.i_size),
	i_capacity(ob.i_capacity)
{
	array = new T[ob.i_capacity];
	if (array == nullptr)
	{
		throw bad_alloc();
	}
	copy(ob.array, ob.array + i_size, array);
}

template<typename T>
void JippVector<T>::print(int i)
{
	cout << array[i] << "\t";
}

template<typename T>
int JippVector<T>::capacity()
{
	return i_capacity;
}

template<typename T>
int JippVector<T>::size()
{
	return i_size;
}

template<typename T>
void JippVector<T>::reserve(int new_capacity)
{
	if (new_capacity > i_capacity)
	{
		T* temp_array;
		temp_array = new T[new_capacity];
		if (temp_array == nullptr)
		{
			throw bad_alloc();
		}
		copy(array, array + i_size, temp_array);

		delete[] array;
	
		array = temp_array;

		i_capacity = new_capacity;
	}
}

template<typename T>
void JippVector<T>::fill(T value_to_fill)
{
	for (int i = 0; i < i_capacity; i++)
	{
		array[i] = value_to_fill;
	}
	i_size = i_capacity;
}

template<typename T>
int JippVector<T>::fill(int start, int len, T value_to_fill)
{
	if ((start + len) <= i_capacity)
	{
		for (int i = start; i < (start + len); i++)
		{
			array[i] = value_to_fill;
		}

		if (i_size < start + len)
		{
			i_size = start + len;
		}
		return 0;
	}
	else
	{
		throw out_of_range("INDEKS POZA ZAKRESEM!");
	}
}

template<typename T>
T& JippVector<T>::operator[](int index)
{
	if (index < 0 || index >= i_size)
	{
		throw out_of_range("INDEKS POZA ZAKRESEM!");
	}
	return array[index];
}

template<typename T>
int JippVector<T>::pushBack(T value_to_add)
{
	if (i_size < i_capacity)
	{
		array[i_size] = value_to_add;
		i_size++;
		return 0;
	}
	else
	{
		i_capacity++;
		T* temp_array;
		temp_array = new T[i_capacity];
		if (temp_array == nullptr)
		{
			throw bad_alloc();
		}
		copy(array, array + i_size, temp_array);

		delete[] array;
		
		array = temp_array;

		array[i_size] = value_to_add;
		i_size++;
	}
}


template<typename T>
int JippVector<T>::pushFront(T value_to_add)
{
	if (i_size < i_capacity)
	{
		for (int i = i_size; i > 0; i--)
		{
			array[i] = array[i - 1];
		}
		array[0] = value_to_add;
		i_size++;
		return 0;
	}
	else
	{
		i_capacity++;
		T* temp_array;
		temp_array = new T[i_capacity - 1];
		if (temp_array == nullptr)
		{
			throw bad_alloc();
		}

		copy(array, array + i_size, temp_array);

		delete[] array;
		array = new T[i_capacity];
		if (array == nullptr)
		{
			throw bad_alloc();
		}

		for (int i = i_capacity; i > 0; i--)
		{
			array[i] = temp_array[i - 1];
		}
		delete[] temp_array;
		array[0] = value_to_add;
		i_size++;
		return 0;
	}
}

template<typename T>
int JippVector<T>::insert(int index, T value_to_add)
{
	if (i_size < i_capacity)
	{
		if (index <= i_size && index >= 0)
		{
			for (int i = i_size; i > index; i--)
			{
				array[i] = array[i - 1];
			}
			array[index] = value_to_add;
			i_size++;
			return 0;
		}
		else
		{
			throw out_of_range("INDEKS POZA ZAKRESEM!");
		}
	}
	else
	{
		if (index <= i_size && index >= 0)
		{
			i_capacity++;
			T* temp_array;
			temp_array = new T[i_capacity];
			if (temp_array == nullptr)
			{
				throw bad_alloc();
			}
			copy(array, array + i_size, temp_array);

			delete[] array;
			array = new T[i_capacity];
			if (array == nullptr)
			{
				throw bad_alloc();
			}
			copy(temp_array, temp_array + i_size, array);
			for (int i = i_size; i > index; i--)
			{
				array[i] = array[i - 1];
			}
			array[index] = value_to_add;
			i_size++;
			return 0;
		}
		else
		{
			throw out_of_range("INDEKS POZA ZAKRESEM!");
		}
	}
}

template<typename T>
int JippVector<T>::erase(int index)
{

	if (i_size == 0)
	{
		throw out_of_range("WEKTOR JEST PUSTY");
	}


	if (index <= i_size && index >= 0)
	{
		for (int i = index; i < i_size - 1; i++)
		{
			array[i] = array[i + 1];
		}
		i_size--;
	}
	else
	{
		throw out_of_range("INDEKS POZA ZAKRESEM!");
	}

}

template<typename T>
int JippVector<T>::erase(int index, int lenght)
{

	if (i_size == 0)
	{
		throw out_of_range("WEKTOR JEST PUSTY");
	}



	if (index + lenght <= i_size  && index >= 0)
	{
		for (int i = index; i < i_size; i++)
		{
			array[i] = array[i + lenght];
		}
		i_size = i_size - lenght;
		return 0;
	}
	else
	{
		throw out_of_range("INDEKS POZA ZAKRESEM!");
	}
}

template<typename T>
bool JippVector<T>::isEmpty()
{
	if (i_size != 0)
	{
		return false;
	}
	else
	{
		return true;
	}
}

template<typename T>
void JippVector<T>::shrinkToFit()
{
	i_capacity = i_size;
	T* temp_array;
	temp_array = new T[i_size];
	if (temp_array == nullptr)
	{
		throw bad_alloc();
	}
	copy(array, array + i_size, temp_array);

	delete[] array;


	array = temp_array;
}

2

Wrzuć cały kod tj. z testami/mainem. Odpal w valgrindzie i zobacz czy nie ma jakichś memory leaków. Zbadaj jak ta pamięć rośnie i kiedy. Bugów masz na pewno duzo, bo wrzucając kod do chatu gpt znalazł oczywisty problem tutaj

  array = new T[i_capacity];

        for (int i = i_capacity; i > 0; i--) // Issue here
        {
            array[i] = temp_array[i - 1];
        }

tj. indeksacja rozmiarem tablicy, gdzie maksymalny indeks to rozmiar - 1

3

po odpaleniu testów

To jak masz reprodukcję to ją wrzuć i nie zmuszaj ludzi do zgadywania co robiliście z tym kodem. A tak poza tym...

    array = new T[i_capacity];
	if (array == nullptr)
	{
		throw bad_alloc();
	}

...jeśli nie implementujesz gdzieś na boku swojego new dla swojej klasy to ta wersja ze standardowej biblioteki rzuci bad_alloc sama z siebie i nie musisz tego robić samemu.

2

Mamy 2024 wiec raczej trzeba by było używać funkcjonalności z C++11/14.
Czyli std::unique_ptr (11) std::vector (98) std::make_unique (14) itp itd.
Brakuje jeszcze copy constructor co w zasadzie gwarantuje problemy.

0

Brakuje jeszcze copy constructor co w zasadzie gwarantuje problemy.

template<typename T>
JippVector<T>::JippVector(const JippVector& ob) :
	i_size(ob.i_size),
	i_capacity(ob.i_capacity)
{
	array = new T[ob.i_capacity];
	if (array == nullptr)
	{
		throw bad_alloc();
	}
	copy(ob.array, ob.array + i_size, array);
}

to jest źle, jako konstruktor kopiujący?

0

to jest źle, jako konstruktor kopiujący?

Ciężko jednoznacznie stwierdzić bo nie wiadomo co robi copy, nie widzę nigdzie implementacji. Zdradzisz czym i jak to kompilujesz? Ta jedna linijka powinna spowodować, że kod nie powinien się skompilować JippVector<T>::JippVector(const JippVector& ob). Nawet bez tego powinieneś mieć warning na warningu, co Ci pokazuje address sanitizer?

3

spojrzałbym jak to działa ale nie ma nagłówka. A co zamierzałem zrobić?
Zacząć od klasyki

  1. clang tidy
  2. valgrind lub
  3. address sanitaizer

To powinno wystarczyć do samodzielnego rozwiązania problemów. na yt są tutorial otworzyć i zreprodukować.

2

Tu (funkcja insert) masz wyciek pamięci. Nie zwalniasz temp_array. Ponadto jedna alokacja jest niepotrzebna. Możesz do temp array przypisać wskaźnik array, a array ustawić na nullptr. Później alokujesz tylko array z nowym rozmiarem i kopiujesz elementy z temp array. Na koniec delete[] temp_array - teraz tego nie ma i masz wyciek.

            i_capacity++;
			T* temp_array;
			temp_array = new T[i_capacity];
			if (temp_array == nullptr)
			{
				throw bad_alloc();
			}
			copy(array, array + i_size, temp_array);

			delete[] array;
			array = new T[i_capacity];
			if (array == nullptr)
			{
				throw bad_alloc();
			}
			copy(temp_array, temp_array + i_size, array);
			for (int i = i_size; i > index; i--)
			{
				array[i] = array[i - 1];
			}
			array[index] = value_to_add;
			i_size++;
			return 0;

1 użytkowników online, w tym zalogowanych: 0, gości: 1