Problem mit free()

SpeckHase

Grünschnabel
Hallo, ich bins wieder.....
ich stehe vor folgendem Dilemma:
Ich habe ein globales Spielfeld:
Code:
struct Feld **feld_ptr;

Dieses beinhaltet wieder pointer auf struct Feld. Also quasi
Code:
struct Feld *Inhalt;

Das Spiel funktioniert nach dem Prinzip Karten-Anlegen.

Wichtig: Die beiden äußeren Spalten SOWIE Reihen sind immer NULL! (Brauche ich für iwelche Prüfmethoden)

Das Spielfeld besteht anfangs deshalb aus 25 Feldern (soll heißen, dass dann nur das Feld in der Mitte belegt ist)

Was nun folgt ist klar: Wenn ich irgendwo am Rand anlege, muss ich das Spielfeld erweitern. Dazu habe ich mir jetzt folgende Funktion geschrieben:

Es geht übrigens hauptsächlich um die Zeilen 38 - 42.....falls irgendjemandem beim 1. Hinsehen der Fehler auffallen sollte.....

Code:
void erweitereSpielfeld(int x, int y, struct Feld *Karte){
    int i, j;
    struct Feld **feld_helper;
   
    if(y == 1){
        if((feld_helper = malloc(xDim * yDim * sizeof(struct Feld*))) != NULL){
            for(i = 0; i < xDim; i++){ //Mache Kopie von altem Feld
                for(j = 0; j < yDim; j++){
                    /////if(feld_ptr[index(i, j)] != NULL){
                    /////    struct Feld *hilfskarte;
                    /////    if((hilfskarte = malloc(sizeof(struct Feld))) != NULL){
                    /////        hilfskarte->N = feld_ptr[index(i, j)]->N;
                    /////        hilfskarte->O = feld_ptr[index(i, j)]->O;
                    /////        hilfskarte->S = feld_ptr[index(i, j)]->S;
                    /////        hilfskarte->W = feld_ptr[index(i, j)]->W;
                    /////        feld_helper[index(i, j)] = hilfskarte;
                    /////    } else Fehler();

                    /////} else feld_helper[index(i, j)] = NULL;

                    feld_helper[index(i, j)] = feld_ptr[index(i, j)];
                }
            }
            if((feld_ptr = realloc(feld_ptr, xDim * sizeof(struct Feld*))) != NULL){
                for(i = 0; i < xDim; i++){ //Erste Spalte erstmal auf NULL setzen
                    feld_ptr[index(i, 0)] = NULL;
                }
                for(i = 0; i < xDim; i++){ //Kopiere altes Feld in neues Feld
                    for(j = 0; j < yDim; j++){
                        feld_ptr[index(i, j + 1)] = feld_helper[index(i, j)];
                    }
                }
                //FELD = Karte; //Speichere neue Karte im Spielfeld
                //yDim++;

            } else Fehler();

           for(i = 0; i < xDim; i++){
                for(j = 0; j < yDim; j++){
                     //free feld_helper
                    printf("bin drin, i: %i  j: %i\n", i, j);
                    free(feld_helper[index(i, j)]);
                }
            }
            yDim++;
            FELD = Karte;
            
        } else Fehler();
    } 


    //free(feld_helper);

}

Der Code zeigt jetzt natürlich nur die Erweiterung in eine einzige Richtung, aber den ganzen Code wär wohl etwas zu viel des Guten.

So: Ihr seht hier die Erweiterung nach "links", also eine Spalte soll links angefügt werden.
Ich dachte mir einfach, ich nehm mir den " **feld_helper "
---> kopier mein aktuelles Feld darein
---> ändere mein eigentliches Feld ab
---> kopiere das alte Feld ins Neue
---> Füge die neue Karte ein.

Tja, klappt nicht. Er hängt sich bei der Position [2][2], also bei der einzigen Karte, die liegt, auf!

Ich habe jetzt halt überlegt, ob es daran liegt, dass beide Spielfelder ja auf denselben Speicherplatz zeigen!?
Dem wollte ich abhelfen, indem ich Zeile 9 - 19 erstellt habe und dort eine ganz neue Struktur erstelle......geht aber auch nicht.

Hat hier irgendjemand eine Lösung dazu?
Oder vllt ne Lösung für das "Erweiterungsproblem" an sich und nicht nur zum free().
Es führen ja bekanntlich viele Wege zum Ziel.

Ich bedanke mich im Voraus schonmal bei allen, die sich die Mühe machen den Text & Code zu lesen******

gruss micha
 
Hi

zeig vllt. doch mal den Komplettcode auch noch.
Hast du das Ganze bis jetzt selbst gemacht oder ist ein gegebenes Programm zu erweitern?

Du vermischt da mehrere Arrayarten (und noch eine Pointerebene dazu).
Ich denk mal, im restlichen Code wird sich erkennen lassen, was da wie drin sein soll.

Das Forensystem ist unter Bearbeitung. Anzeigefehler liegen eventuell daran und werden in dem Fall noch behoben.
 
naja, das sind >800 Zeilen Code, ich bezweifel, dass sich das hier irgendjemand antun möchte.....
also was ich gemacht habe, ist halt ein array von pointern auf meinen eigenen Datentyp "Feld".
Dabei habe ich mich an diesem Beispiel hier orientiert: http://www.linjux.org/blog/2010/09/c-refreshment---pointer-of-struct-pointer-array.html

Des weiteren ist mein Spielfeld ja eigentlich in 2-D, in dem array aber halt nur in 1-D. Deshalb greife ich immer mit "index(x, y)" auf die richtige Position im 1-D array zu. (Index(x, y) gibt halt einfach (x * yDim) + y zurück, das Prinzip sollte klar sein !******)

Was vllt noch interessant sein könnte ist die Funktion, in der ich den Feld_ptr initialisiere:
Code:
void FeldInit(void){
    if((feld_ptr = malloc(25 * sizeof(struct Feld*))) != NULL){
        printf("Feld initialisiert!\n");
    } else Fehler();
    int i, j;
    for(i = 0; i < 5; i++){
        for(j = 0; j < 5; j++){
            feld_ptr[index(i, j)] = NULL;
        }
    }
    struct Feld *ersteKarte;
    if((ersteKarte = malloc(sizeof(struct Feld))) != NULL){
        ersteKarte->N = 2;
        ersteKarte->O = 1;
        ersteKarte->S = 0;
        ersteKarte->W = 1;
        xDim = 5;
        yDim = 5;
        feld_ptr[index(2, 2)] = ersteKarte;

    } else Fehler();
}

edit: achso, das Programm ist übrigens komplett von mir und soll nicht nur erweitert werden
 
Hi.

Erstmal scheint ein Array für deine Zwecke relativ wenig geeignet. Eine (doppelt) verkette Liste wäre m.M. nach besser.

Dann ist das Kopieren komplett unnötig. realloc kopiert die Arraydaten bereits. Außerdem brauchst du realloc für das globale Feld gar nicht aufrufen, wenn du die y Dimension änderst.

Dann darfst du natürlich in der Funktion erweitereSpielfeld Zeile 42 nicht free aufrufen, da du gar keinen Speicher für die Elemente im Hilfsfeld angelegt hast.

Gruß
 
Dann darfst du natürlich in der Funktion erweitereSpielfeld Zeile 42 nicht free aufrufen, da du gar keinen Speicher für die Elemente im Hilfsfeld angelegt hast.

Gruß

Hi,
wenn du jetzt beim Code in meinem Eingangspost Zeile 9-19 betrachtest: Da erstelle ich doch neue Elemente fürs Hilfsfeld, oder!****** Das free() funktioniert dann aber trotzdem nicht.....


Zur doppelt verketteten Liste: Kannst du mir das vllt mal etwas näher erklären?
Ich hatte auch schon überlegt, so etwas in der Art zu machen, aber ich wüsste nicht, wie ich dann in dem array manövrieren soll, da es ja nicht nur 1-dimensional, sondern ein 2-D-Spielfeld sein soll.....
 
Hi,
wenn du jetzt beim Code in meinem Eingangspost Zeile 9-19 betrachtest: Da erstelle ich doch neue Elemente fürs Hilfsfeld, oder!******
Nö, das ist ja auskommentiert. Wenn du das einkommentierst und Zeile 21 auskommentierst, dann mußt du free aufrufen. Aber nicht für die Elemente in feld_helper, sondern die Elemente in feld_ptr, da du diese ja mit denen aus feld_helper überschreibst.
Zur doppelt verketteten Liste: Kannst du mir das vllt mal etwas näher erklären?
Mir sagt das Spiel "Karten anlegen" nicht wirklich etwas. Aber im Grunde gibt es ja nur begrenzt viele Karten, oder? Und begrenzt viele Stapel / Anlegemöglichkeiten?

Wenn man Karten anlegen kann, dann ist das ja eine append Operation auf einer Listenstruktur. Also kann ein Stapel (vermutlich) relativ gut durch eine Liste repräsentiert werden.

Gruß
 
Danke schonmal, hab jetzt auf jeden Fall schonmal EINEN Durchlauf ohne Fehler.
Ohne jetzt den ganzen Code posten zu wollen (hab da eh noch etliche Sachen auskommentiert und ist total verworren grade), ist meine Logik die folgende:
1) Kopie vom alten Feld machen, und dabei alle Karten NEU erstellen und im alten Feld mit free löschen
2) das alte Feld komplett löschen(also auch den Ausgangspointer) und komplett neu erstellen (ohne realloc halt, das ging iwie nicht)
3) wie bei 1) alle Karten von der Kopie neu erstellen und ins neue Feld kopieren, die kopierten Felder dabei mit free löschen
4) Ausgangspointer von der Kopie des Feldes mit free löschen.

So, ich hoffe mit der Methode komme ich nun etwas voran. Mein Kopf platzt glaub ich auch jeden Moment....hatte nicht gedacht, dass C einen so viel mehr fordert als andere Sprachen.....


Und zu deinem Vorschlag mit den verketteten Listen: Mein größtes Problem ist, dass ich jetzt schon einige Funktionen erstellt habe, die Berechnungen auf dem von mir erstellten array durchführen......die müsste ich dann alle nochmal neu schreiben, deshalb versuch ich es jetzt erstmal so weiter, auch wenn es wohl eher nicht die allerschnellste Möglichkeit ist, wenn ich alles doppelt und dreifach erstellen muss^^

gruss micha
 
Ohne jetzt den ganzen Code posten zu wollen (hab da eh noch etliche Sachen auskommentiert und ist total verworren grade), ist meine Logik die folgende:
1) Kopie vom alten Feld machen, und dabei alle Karten NEU erstellen und im alten Feld mit free löschen
2) das alte Feld komplett löschen(also auch den Ausgangspointer) und komplett neu erstellen (ohne realloc halt, das ging iwie nicht)
3) wie bei 1) alle Karten von der Kopie neu erstellen und ins neue Feld kopieren, die kopierten Felder dabei mit free löschen
4) Ausgangspointer von der Kopie des Feldes mit free löschen.
Wie gesagt ist das bei einer Erweiterung der y Dimension ziemlich unnötig. Ein realloc der einzelnen Spalten reicht doch.

Bei Erweiterung der x Dimension reicht ein realloc des globalen Feldes und ein Initialisieren der neuen Spalten.

Gruß
 
Wie gesagt ist das bei einer Erweiterung der y Dimension ziemlich unnötig. Ein realloc der einzelnen Spalten reicht doch.

Bei Erweiterung der x Dimension reicht ein realloc des globalen Feldes und ein Initialisieren der neuen Spalten.

Gruß

Irgendwie steh ich grad ziemlich aufm Schlauch.....
Jetzt mal als Beispiel: Ich habe ein 5x5 Spielfeld.
Das Bild zeigt jetzt, mit welchem Index ich die in meinem Array erreichen kann
Code:
----------------------
| 0   1  2  3  4  |
| 5   6  7  8  9  |
| 10 11 12 13 14 |
| 15 16 17 18 19 |
| 20 21 22 23 24 |
----------------------
edit: Keine Ahnung, ob das bei jedem so ist, aber mein Browser zeigt mir in den letzten Zeilen ne Skype-Nr. an......hoffe es ist trotzdem verständlich

Wenn ich jetzt ganz unten eine Zeile einfüge stimme ich mit dir überein: Ich mach mit realloc einfach ne Erweiterung um (in diesem Fall 5) Werte und belege einfach die Positionen 25, 26, 27, 28, 29 neu!
Aber wie willst du das machen, wenn du rechts, links oder oben erweiterst?
 
Zuletzt bearbeitet:
ok....die Logik, oben ne Spalte zu erweitern kriege ich auch noch hin......wenn ich dann mit realloc wieder um 5 Werte erweiter, müsste ich alle Werte einfach um 5 nach vorne verschieben, von hinten angefangen, also
24 -> 29
23->28
....
0 -> 5

aber wie machste das bei Erweiterung nach rechts/links****?
 
Zurück