PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ANSI C] free funktioniert nicht?


Funky Bob
2008-12-01, 13:14:34
Hallo,
ich habe ein Problem mit der free-Funktion in C.

Meine Aufgabe ist es eine verkettete Liste zu erstellen. Das Programm läuft auch soweit, nur habe ich gerade mal testweise 100000 Elemente erstellt und diese wieder gelöscht.

Nur anders als erwartet nimmt der Speicherverbrauch nicht ab, sondern sogar zu!

Die Deklaration des Structs sieht so aus:

struct list{
int number;
struct list * ptr;};

char *end;
char *start;

Dann das einfügen passiert folgendermaßen:

//Weiteres Element hinten anhängen
void enqueue(int element)
{
//Neue Zeigerstrukturen erstellen und Speicher reservieren
struct list *newele;
struct list *helpele;
newele=malloc(sizeof(*newele));
helpele=malloc(sizeof(*helpele));
//Falls nur das Endelement existiert das erste Element erstellen
if(isempty()!=0)
{
newele->number=element;
newele->ptr=end;
start=newele;
}
//Ansonsten das vorletzte Element suchen, dessen Zeiger auf die neue Struktur legen
//und bei der neuen Struktur den Ptr aufs Endelement setzen.
else
{
newele->number=element;
newele->ptr=end;
helpele=start;
while(helpele->ptr!=end)
{
helpele=helpele->ptr;
}
helpele->ptr=newele;
}
}

Und dann das Ausgeben und Löschen des letzten Elementes:

//Löschen und Ausgabe des ersten Elementes
int dequeue()
{
//Falls Liste nicht leer
if(isempty()==0)
{
//Zeigerstructs erstellen, Speicher reservieren
struct list *oldele;
struct list *newstartele;
oldele=malloc(sizeof(*oldele));
newstartele=malloc(sizeof(*newstartele));
//Zu löschende Struktur auf den Startwert legen
oldele=start;
//Zukünftiges neues Element festlegen, start auf das neue Element legen
newstartele=oldele->ptr;
start = newstartele;
//Ausgabe
if(isempty()==0)
{
printf("Element mit Wert %d geloescht, neues erstes Element hat den Wert %d\n\n",oldele->number,newstartele->number);

}
else
{
printf("Letztes verbleibendes Element mit dem Wert %d geloescht!\n\n",oldele->number);
}
//Freigeben des Speicherplatzes
free(oldele);
}
else
{
printf("Keine Elemente zum loeschen vorhanden!\n\n");
}
}


Nun habe ich von verschiedenen Personen gehört, man müsse bei Strukturen erst die einzelnen Unterpunkte freigeben und dann zum Schluß das große Ganze. Dies führt aber zu Fehlermeldungen während des Löschens.


Wenn ich den Code so nutze, wie er oben steht kompiliert er zwar, aber das Freigeben des Speichers belegt komischerweise mehr Speicher als vorher?!

Xmas
2008-12-01, 14:08:23
Kein Wunder, du hast ja auch Speicherlecks. Einfache Regel: Jedes mal wenn du Speicher mit malloc reservierst musst du ihn auch wieder mit free freigeben. Du hast 4 Aufrufe von malloc in deinem Code, aber nur einen von free.

Funky Bob
2008-12-01, 14:08:45
Ok, hab eine Lösung gefunden und hoffe sie ist auch eine...

Wenn ich im letzten Schritt die Struktur zwar deklariere, aber den Speicher nicht mehr per malloc reserviere, steigt der Speicherverbrauch nicht mehr weiter an, nachdem ich free benutzt habe.


Außerdem habe ich nachgelesen, dass freigegebener Speicher nicht automatisch an das OS weitergereicht wird, sondern in nem Malloc-Speicher weiter freigehalten wird.

Hoffe das ist so richtig, wenn nciht bitte melden!

Funky Bob
2008-12-01, 14:08:57
sorry 4 doppelpost...

Aber wo ich schonmal eine Antwort habe:

Da ich nun die mallocs auf 2 reduziert, und zwar habe ich im letzten Abschnitt nun:

//Löschen und Ausgabe des ersten Elementes
int dequeue()
{
//Falls Liste nicht leer
if(isempty()==0)
{
//Zeigerstructs erstellen
struct list *oldele;

//Zu löschende Struktur auf den Startwert legen
oldele=start;
//Zukünftiges neues Element festlegen, start auf das neue Element legen
start = oldele->ptr;
//Ausgabe
if(isempty()==0)
{
printf("Element mit Wert %d geloescht.\n\n",oldele->number);
}
else
{
printf("Letztes verbleibendes Element mit dem Wert %d geloescht!\n\n",oldele->number);
}
//Freigeben des Speicherplatzes
free(oldele);
}
else
{
printf("Keine Elemente zum loeschen vorhanden!\n\n");
}
}

Darf ich denn bei der Elementerstellung den Speicher überhaupt wieder freigeben? Da ich den Wert ja noch verwenden muss? Oder wäre das nun so richtig, wie in diesem Codeschnippsel beschrieben, sodass ich keine Speicherlecks mehr habe?

Danke dir/euch!


Ok bin den ganzen anderen Code nochmal durchgegangen und konnte fast überall das malloc löschen, habe nun nur noch 2 Mallocs im gesamte Programm, einmal für das Endelement in der Initialisierung und für jedes neue Element, wobei die neuen Elemente nach dem Löschen auch wieder freigegeben werden.

Nun verhält sich die Speicherauslastugn auch so wie erwartet (mit dem Wissen dass das OS den Speicher nicht direkt zurück bekommt sondern ein temporärer mallocspeicherbereich freigegeben für das Programm reserviert bleibt.)


Sorry für die Umstände, bin blutiger Anfänger :)

Danke! Kann geschlossen werden.