• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

ALLEGRO 5 [Język C, zwiększanie tablicy]

Object Storage Arubacloud
0 głosów
292 wizyt
pytanie zadane 24 grudnia 2018 w C i C++ przez niezalogowany
Witam, piszę Snake'a w języku C przy pomocy ALLEGRO 5 i natknąłem się na problem zwiększania węża po zjedzeniu owoca, do pewnego momentu wszystko dobrze działa, lecz potem wyrzuca błąd o wycieku pamięci. Zakładam, że źle korzystam z funkcji realloc (funkcja addNode). Byłbym wdzięczny, gdyby ktoś mógł mi wyjaśnić w czym jest problem.

Kod: https://pastebin.com/XpVkgiSB

1 odpowiedź

+1 głos
odpowiedź 24 grudnia 2018 przez j23 Mędrzec (194,920 p.)
wybrane 24 grudnia 2018
 
Najlepsza
void addNode(struct Snake *snake, struct Node *prev)
{
	/* ... */
	
	prev = (struct Node *)realloc(prev, snake->length * sizeof(struct Node));
}

To powoduje wyciek pamięci. Jeśli już, to tak:

void addNode(struct Snake *snake, struct Node **prev)
{
	/* ... */

	*prev = (struct Node *)realloc(*prev, snake->length * sizeof(struct Node));
}

 

komentarz 24 grudnia 2018 przez niezalogowany
I w jaki sposób to ma działać? Przecież realloc, jako pierwszy argument przyjmuje adres wskaźnika, który chce zwiększyć.
komentarz 24 grudnia 2018 przez RafalS VIP (122,820 p.)

Przekazujesz wskaznik przez wartosc i probujesz cos do niego przypisac czyli taka sytuacja:

void f(int x)
{ x= 5; }

 

komentarz 24 grudnia 2018 przez j23 Mędrzec (194,920 p.)

@wixy0, problem w tym, że prev w twojej wersji funkcji jest lokalnym wskaźnikiem, to zwiększanie pamięci ma lokalny charakter. Zatem to, co dasz w drugim parametrze funkcji, nie zostanie zwiększone. W mojej wersji trzeba podać wskaźnik na wskaźnik, dzięki czemu przypisanie adresu będzie widoczne po wyjściu z funkcji.

komentarz 24 grudnia 2018 przez niezalogowany
edycja 24 grudnia 2018
Chociaż może zamiast komplikować tak sprawy lepiej zrobić to od razu w funkcji logic. W jaki sposób odnosić się do składowych albo do tego wskaźnika, jeżeli argumentem jest dajmy na to struct Snake **snake. Np. nie wiem jak dostać się do składowej length, żeby ją zwiększyć.
komentarz 24 grudnia 2018 przez j23 Mędrzec (194,920 p.)

W jaki sposób odnosić się do składowych albo do tego wskaźnika

(*snake)->składowa

 

Choć nie wiem, po co snake miałaby być wskaźnikiem na wskaźnik.

komentarz 24 grudnia 2018 przez niezalogowany
Muszę też modyfikować wielkość tablicy nodes, która jest składową snake.
komentarz 24 grudnia 2018 przez j23 Mędrzec (194,920 p.)

W takim razie nie musisz przekazywać struktury Snake przez wskaźnik na wskaźnik. Tak jak masz teraz, jest ok.

komentarz 24 grudnia 2018 przez niezalogowany
To poprawiony kod: https://pastebin.com/9QvKhxvv

Korzystając z okazji, natknąłem się na błąd który może wynikać z tego w jaki sposób Allegro obsługuje wydarzenia ale nie jestem pewien. Otóż jak wąż będzie się składał z więcej niż 3 kwadratów i np. poruszając się w górę w prawie jednym momencie nacisne strzałke w lewo/prawo i w dół to zalicza to jako kolizje. Czy da radę jakoś wyeliminować ten błąd, np nie pozwalając wciskać dwóch klawiszy na raz?
komentarz 24 grudnia 2018 przez j23 Mędrzec (194,920 p.)

Pisałem przecież , że nie musisz przekazywać Snake'a przez podwójny wskaźnik. Tak wystarczy:

void logic(struct Snake *snake, struct Node *fruit, struct Node **prev)
{
	//KOLIZJA Z GRANICAMI PLANSZY
	if (snake->head->y < 0)
		gameOver = 0;
 
	if (snake->head->y > H - recSize)
		gameOver = 0;
 
	if (snake->head->x < 0)
		gameOver = 0;
 
	if (snake->head->x > W - recSize)
		gameOver = 0;
 
	//ZJEDZENIE OWOCU
	if (snake->head->x == fruit->x && snake->head->y == fruit->y)
	{
		snake->length++;
		snake->nodes = (struct Node *)realloc(snake->nodes, snake->length * sizeof(struct Node));
		*prev = (struct Node *)realloc(*prev, snake->length * sizeof(struct Node));
 
		fruit->x = (rand() % (W / recSize - 1) + 1) * recSize;
		fruit->y = (rand() % (H / recSize - 1) + 1) * recSize;
	}
 
	//KOLIZJA Z OGONEM
	for (int i = 0; i < snake->length; i++)
		if (snake->head->x == snake->nodes[i].x && snake->head->y == snake->nodes[i].y)
			gameOver = 0;
}

Czy da radę jakoś wyeliminować ten błąd, np nie pozwalając wciskać dwóch klawiszy na raz?

Zapewne musisz obsłużyć zdarzenia ALLEGRO_EVENT_KEY_DOWN i ALLEGRO_EVENT_KEY_UP, czyli nie reagujesz na key-down, jeśli poprzednie naciśnięcie nie zakończyło się zdarzeniem key-up.

Podobne pytania

0 głosów
1 odpowiedź 265 wizyt
pytanie zadane 25 grudnia 2018 w C i C++ przez niezalogowany
0 głosów
1 odpowiedź 338 wizyt
pytanie zadane 6 stycznia 2019 w C i C++ przez Sebastian Plichta Obywatel (1,200 p.)
0 głosów
1 odpowiedź 140 wizyt
pytanie zadane 17 stycznia 2019 w C i C++ przez niezalogowany

92,555 zapytań

141,402 odpowiedzi

319,552 komentarzy

61,939 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...