Frage Speicherfreigabe
-
Hallo !
und wieder bin ich mit der Speicherei überfragt.
Ich habe einen Stack programmiert welche Zeichenketten speichert. Für die zu speichernde Zeichenkette allokiere ich Speicher in der passenden Länge. Nachdem ich die Zeichenkette in meinem Array habe (nach meinem Push) und ich den Speicher der Zeichenkette freigebe ist Sie nicht mehr im Array, richtig ?
Also gebe ich den Speicher nach dem pop für den entsprechende Array-Index frei oder ?Hier mal die wichtigen Funktionen:
eingabezeugs: .... { ... printf("Geben Sie den Wert ein: "); scanf("%s", &swap); val = (char*) malloc(sizeof(char) * (strlen(swap) + 1)); strcpy(val, swap); printf("Ihre Eingabe war: %s\n", val); push(val, &counter); /* Hier kann ich den Speicher nicht freigeben ? */ ... } char* pop(int *counter) { char* swap = stack[*counter - 1]; free(stack[*counter - 1]); *counter = (*counter - 1); printf("swap: %s\n", swap); return swap; } void push(char* element, int *counter) { printf("Counter: %d\n", *counter); stack[*counter] = element; *counter = *counter + 1; }
Schönheitsfehler nicht beachten geht nur im die speicherfreigabe an der richtigen Stelle.
Danke schonmal !
-
*Schönheitsfehler nicht beacht*
Wenn du die Zeichenkette freigibst wird nur der Speicher für die Zeichenkette freigegeben. In deinem Array befindet sich immernoch der Pointer für die ehemals gültige Zeichenkette. Wenn du darauf zugreifst krachts.
Der Kommentar in Zeile 11 ist korrekt, du kannst den Speicher noch nicht freigeben, denn den brauchst du noch.
Nach Zeile 11 kommt irgendwie noch Code und dann irgendwann... val = pop(&counter); //nutze val sinnvoll printf("habe '%s' vom Stack geholt, bin damit jetzt fertig\n", val); free(val); ...
Das klappt natürlich nur wenn das val was du pushst auch mit malloc gebaut wurde. Wenn du sowas wie
push("test", counter);
machst gehts nicht.
Ich würde dir empfehlen in push nicht val sondern eine Kopie von val zu speichern, dann kannst du immer free benutzen auch wenn du nicht durch malloc erzeugte Strings speicherst.
*Schönheitsfehler doch beacht*
Wieso übergibst du counter an push und pop? Und wieso ist counter ein int* und kein int? Der Sinn des Stacks ist dass er sich alleine managt ohne dass du dich um sowas wie counter kümmern musst.
Und Arrays sind böse und fressen kleine Kinder, wieso glaubt mir das keiner?Deine Funktionen sollten ungefähr so aussehen:
struct stackelement{ char *value; struct stackelement *previous; }; struct stack{ struct stackelement *top; }; char* pop(struct stack* s){ struct stackelement *t; char *returnvalue; if (s->top){ //oberstes stackelement gefunden, wird gelöscht und Wert wird zurückgegeben t = s->top->previous; returnvalue = s->top->value; free(s->top); s->top = t; return returnvalue; } else return 0; //Stack ist leer } void push(char* element, struct stack *s){ // TODO: //neues stackelement erzeugen //stackelement-Einträge auf die richtigen Werte setzen //s->top anpassen }
Du kannst in struct stack noch die Anzahl der Elemente mitzählen wenn du sowas brauchst.
-
nwp2 schrieb:
Und Arrays sind böse und fressen kleine Kinder, wieso glaubt mir das keiner?
Versuche mal dir die Frage selbst zu beantworten.
-
Also wenn mein Pop() kommt schreib ich es so wie du:
... val = pop(&counter); //nutze val sinnvoll printf("habe '%s' vom Stack geholt, bin damit jetzt fertig\n", val); free(val); ...
und der Speicher von dem Element ist frei und es steht an der stelle nichts mehr im array ?
-
Doch, es steht dasselbe im Array was vorher auch drin stand.
Der Unterschied ist, dass vor free(val) der Pointer im Array auf ein gültiges Element zeigt und dann free das Element entfernt, sodass der Pointer jetzt auf ein nicht mehr existierendes Element zeigt. Und auf nicht existierende Elemente zuzugreifen ist eine schlechte Idee.Edit: Vielleicht ist dir das schon klar, aber im Array stehen nicht die Elemente sondern nur Referenzen wo drin steht wo man das Element findet.
Die Elemente und die Referenzen auf die Elemente haben erstmal nichts miteinander zu tun. Du musst selbst dafür sorgen dass die Referenzen immer aktualisiert werden wenn Elemente verschwinden oder neu erscheinen.
-
Ok soweit alles klar.
Wenn ich nachdem Free dem Pointer im Array noch löschen will wie mach ich das ?
Kann ich die entsprechende Array-Stelle =NULL setzen ?
Will keine Pointer im Array haben die ins Nirvana zeigen.
-
Ja, es ist üblich Pointer die auf kein Element zeigen auf 0 zu setzen.
Dann kannst du sowas bauen:for (int elementnummer = 0; elementnummer<Arraylänge-1; elementnummer++){ if (element = array[elementnummer]) tuwasmit(element);//Element existiert, tu was sinnvolles else printf("Element nummer %d existiert nicht!", elementnummer); //Element existiert nicht, wird übersprungen }
-
Ok, dann vielen Dank euch allen