2016-10-15 5 views
0

Ich habe ein Array von Zeigern auf Strukturen, die ich versuche, free() zu verwenden, sobald sie nicht mehr benötigt werden. Unten ist, wie diese Strukturen sind Setup:C: Segfault Mit Free()

typedef struct { 
    SDL_Surface *sprite; 
    SDL_Rect rect; 
} Laser; 

Laser *fireLaser(char *sprite, int x, int y) 
{ 
    Laser *laser = malloc(sizeof(Laser)); 

    laser->sprite = loadSurface(sprite); 
    laser->rect.x = x; 
    laser->rect.y = y; 

    return laser; 
} 

game->playerLasers[player->laserCount++] = fireLaser("images/laser.bmp", (player->rect.x, player->rect.y); 

Sobald man nicht mehr benötigt wird, versuche ich free() auf, es zu benutzen.

SDL_FreeSurface(game->playerLasers[i]->sprite); 
free(game->playerLasers[i]); 

Ich kompiliere dies mit free(game->playerLasers[i]); und bekomme keine Warnungen oder Fehler. Das Programm läuft, aber sobald free() läuft, bekomme ich einen Segmentierungsfehler.

Wenn ich das Programm mit valgrind betreiben ich seltsam nicht die Segmentierungsfehler bekommen, aber ich habe die folgende Ausgabe einmal free() erhalten ist ran:

==2010== Invalid read of size 8 
==2010== at 0x4012D8: spawnGrunts (main.c:196) 
==2010== by 0x4013FC: updates (main.c:219) 
==2010== by 0x4016CD: main (main.c:277) 
==2010== Address 0xcfce9c0 is 0 bytes inside a block of size 32 free'd 
==2010== at 0x4C2AD90: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==2010== by 0x4012FF: spawnGrunts (main.c:197) 
==2010== by 0x4013FC: updates (main.c:219) 
==2010== by 0x4016CD: main (main.c:277) 
==2010== Block was alloc'd at 
==2010== at 0x4C29BBE: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==2010== by 0x400E65: loadGrunt (main.c:105) 
==2010== by 0x4011FE: spawnGrunts (main.c:182) 
==2010== by 0x4013FC: updates (main.c:219) 
==2010== by 0x4016CD: main (main.c:277) 
==2010== 
==2010== Invalid free()/delete/delete[]/realloc() 
==2010== at 0x4C2AD90: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==2010== by 0x4012FF: spawnGrunts (main.c:197) 
==2010== by 0x4013FC: updates (main.c:219) 
==2010== by 0x4016CD: main (main.c:277) 
==2010== Address 0xcfce9c0 is 0 bytes inside a block of size 32 free'd 
==2010== at 0x4C2AD90: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==2010== by 0x4012FF: spawnGrunts (main.c:197) 
==2010== by 0x4013FC: updates (main.c:219) 
==2010== by 0x4016CD: main (main.c:277) 
==2010== Block was alloc'd at 
==2010== at 0x4C29BBE: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==2010== by 0x400E65: loadGrunt (main.c:105) 
==2010== by 0x4011FE: spawnGrunts (main.c:182) 
==2010== by 0x4013FC: updates (main.c:219) 
==2010== by 0x4016CD: main (main.c:277) 

Würde mir jemand auf dieser Lage sein, einen Hinweis zu geben ein?

+0

Sind Sie sicher, dass Sie den Heap nicht anderweitig in Ihrem Code verfälschen? –

+1

warum einfach 'Laser' ohne Zeiger nicht verwenden? bedeutet ohne Zuteilung/Freigabe? Schließlich ist es eine kleine Struktur, kann ohne Probleme kopiert werden. (Vielleicht befreien Sie die Strukturen mehr als einmal) –

+0

Wenn Sie den Laser zuweisen, erhöhen Sie eine Zählung: 'player-> laserCount ++'. Wenn Sie diesen Laser "frei" machen, muss der Eintrag im Array entfernt werden, und die Anzahl muss verringert werden. Ich nehme an, dass Sie das nicht tun, und das Ergebnis ist, dass Sie Zeiger im Array haben. – user3386109

Antwort

0

Wenn Sie Ihr Programm unter valgrind ausführen, werden Sie die meiste Zeit nicht abstürzen, weil Sie in einem Speicherbereich laufen, der von valgrind erstellt wurde, der also für Ihr Programm so fehlerverzeihend ist.

Sie werden in der Regel keinen Kompilierungsfehler haben, wenn Sie nicht versuchen, einen Nicht-Zeigertyp freizugeben. Aber es wird zur Ausführungszeit abstürzen, weil Sie versuchen werden, eine schlechte Adresse zu befreien.

Ich wäre sehr daran interessiert, Ihre Funktion zu sehen, die Ressourcen zu befreien, die komplette.

Sind Sie an einem Ort, der die Größe Ihres Arrays überwacht? Setzen Sie das Array [i] auf NULL, um anzuzeigen, dass es freigegeben wurde und nicht mehr verwendbar ist?

Setzen Sie Ihre Zeiger immer auf NULL, wenn sie nicht verwendbar sind.

+0

Es kann einfacher sein, um meinen Code zu verknüpfen auf GitHub [hier] (https://github.com/azurepancake/space-man/blob/master/main.c). Die Funktion, die ich versuche, mit dem Aufräumen fertig zu werden, ist 'shootLasers()'. Im Moment setze ich mein Array [i] wieder auf 0 zurück, sobald es sich dem Maximum nähert. – azurepancake