zwiększanie rozmiaru tablicy, błąd przy dealokacji pamięci

0

Witam. Mam za zadanie stworzyć klasę, która wykorzystując operatory przeciążone, będzie reprezentowała zbiory i operacje na nich. Do dyspozycji mam tylko i wyłącznie tablice dynamiczne. Póki co mam problem z zwiększaniem rozmiaru tablicy, przy dodawaniu kolejnych elementów. W zasadzie sprawa wydawała mi się stosunkowo prosta: tworzę tymczasową tablicę(temp), kopiuję do niej elementy z tablicy reprezentującej zbiór(set), zwalniam pamieć zarezerwowaną przez set, alokuję nową, większą tablicę, po czym kopiuje do niej zawartość temp oraz nowe elementy. Na koniec zwalniam pamięć zajmowaną przez temp... i tu wlasnie pojawia się problem, którego na ten moment nie bardzo jestem w stanie pojąć. Oto mój kod:

 
//Sets.cpp
Sets::Sets(int s)
{
	this->size = 1;
	set = new int[size];
	set[0] = s;
}

Sets::~Sets()
{
}

bool Sets::isElem(int elem)
{
	
	for (int i = 0; i < size; i++)
	{
		if (elem = set[i])
			return true;
	}
	return false;
}

void Sets::resize(int length)
{
	int *temp = new int(size);
	int new_size = length + size;
	for (int i = 0; i < size; i++)
	{
		temp[i] = set[i];
		
	}
	delete[]set;
	

	set = new int[new_size];
	for (int i = 0; i < size; i++)
	{
		set[i] = temp[i];
		
	}
	size = new_size;

	delete[]temp; //linijka powodujaca blad
	
}
//dodaje do zbioru wszystkie elementy tablicy
void Sets::addFromArray(int *array, int length)
{
	
	resize(length);
	
	for (int i = size - length, j = 0; i < size; i++, j++)

	{
		this->set[i] = array[j];
	}
	
}
void Sets::show()
{
	
	for (int i = 0; i < size; i++)
	{
		std::cout << set[i] << ",";
	}
}

//dodaje do zbioru prawostronny operand
void Sets::operator+(int elem)
{
		resize(1);
		this->set[size - 1] = elem;
}

Przy próbie wywołania operatora delete dla tablicy temp wywala wyjątek "Heap Corruption detected". Bez tej linijki wszystko działa prawidłowo(pomijając wyciek pamięci). Nie bardzo rozumiem czemu tak się dzieje(serio szukałem i nie mogę doszukać się żadnego wyjechania poza zakres sterty, ale trochę juz późno więc może coś przeoczyłem..;) ) Dodam jeszcze, że błąd pojawia się dopiero przy drugim wywołaniu operatora + w funkcji Main:

 

//Main.cpp
#include"Sets.h"



int main()
{
	Sets s(4);

	s + 5; //to jeszcze działa prawidłowo
	s + 6; // tu się wysypuje

	s.show();


	system("pause");
}

Jako, że to moje pierwsze kroki z C++, prosiłbym o wytłumaczenie czemu tak się dzieje, jak i o wytknięcie wszystkich innych błędów jakie tu mogłem popełnić. Z góry dzięki ;)

3

int *temp = new int(size);

[] i () to nie to samo.

ponadto:

  1. pomijając zadania tego typu, gdzie masz zrobić to sam, używaj kontenerów z biblioteki standardowej, np. std::vector
  2. s + 5; //to jeszcze działa prawidłowo WTF. operator+ nie powinien pod żadnym pozorem zmieniać operandów :|
  3. respektuj the rule of three/five/zero. W tym przypadku nie możesz użyć zero, ale powinieneś do tego aspirować.
  4. zwalniaj pamięć w destruktorze.
  5. relatywne resize? Tego nawet Hitler nie robił :|
  6. show nie powinno być metodą (SRP). Jeśli już - przeładuj operator<< dla std::ostream
  7. kopiowanie za pomocą pętli jest średnio wygodne, użyj std::copy
  8. if (elem = set[i]) przypisanie zamiast porównania
  9. system("pause"); używaj IDE łapiącego konsole zamiast tego potworka.
1

Poprzepisywałbym jeszcze te dane kilka razy dla pewności.

0

Dzięki wielkie za rady, jednak nie wszystko czaję:

operator+ nie powinien pod żadnym pozorem zmieniać operandów :|

Racja, kompletnie to bez sensu. Chyba bardziej w tę stronę powinno to wyglądać?

 
Sets Sets::operator+(int elem)
{
	Sets s;
	s.set = new int[this->size + 1];

	std::copy(this->set[0], this->set[this->size-1], s.set);
	s.set[this->size] = elem;
        delete[] this->set;

	return s;


int main()
{
	Sets s(4);
	s.setS(0, 2);
	s.setS(1, 6);
	s.setS(2, 1);
	s.setS(3, 3);
	Sets sum;
	
	sum = s + 5;
	
	return 0;
}

}

Tylko, że kompilator nie chce przepuścić linii z std::copy. Próbowałem w miejsce argumentów uzyć std::begin i end ale to tez nie trybi...

zwalniaj pamięć w destruktorze.

Tylko tyle?

Sets::~Sets()
{
	delete[] set;
	
}

relatywne resize? Tego nawet Hitler nie robił :|

Nie rozumiem :) Jak zatem powinienem zmieniać rozmiar tablicy set? Z drugiej strony po modyfikacji w operator+ metoda ta jest mi póki co zbędna.

1

std::copy(this->set[0], this->set[this->size-1], s.set); close, but no cigar

std::copy(set, set+size, s.set);

co do relatywnego resize: konwencją jest, że do resize podajesz nową ilość elementów w kontenerze. Chcesz mieć 42? c.resize(42) a nie c.resize(42 - c.size())

0

Co do std::copy to okazało się, że musiałem dodać definicję _SCL_SECURE_NO_WARNINGS preprocesora aby ruszyło. Co do zwalniania pamięci w destruktorze, dlaczego taka postać jaką podałem może być nieprawidłowa? Nawet jeśli w całym kodzie ani razu nie użyję operatora delete to i tak wywala mi błąd próby usunięcia czegoś co już nie istnieje...

        Sets sum;

	sum = s + 7; //w tym momencie wywala błąd

Czy powodem może być niepoprawnie zdefiniowany konstruktor kopiujący?

Dobra, poradziłem sobie. Rzeczywiście powodem był konstruktor kopiujący i operator przypisania (całkiem szybko przekonałem się o zasadności wspomnianej przez @kq rule of three :) )

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