speicherverwaltung unter c

Hallo Zusammen,

also ich habe grad eines meiner ersten c programme geschrieben.
dabei wird ein Adressblock angefordert mit calloc, und der dann einem array zugewiesen. hinterher soll der speicher wieder freigegeben werden mit realloc.

meine frage:
wie kann ich testen ob der speicher wieder frei ist?

die variablen sind komischerweise noch da...
das kann aber auch heissen dass sich das system wieder selbst um die speicherverwaltung kümmert, so als wenn man die variable ohne speicheranforderung anlegen würde. oder?

danke im voraus,
Peter.
 
also wenn ich dich richtig verstehe guckst du nach dem freigeben des speichers nochmal nach, was da steht? beim freigeben wird der speicher nicht überschrieben. erst wenn er wieder benutzt wird kommt in den bereich etwas neues. daher kann es passieren, dass du schon noch deine werte darin findest. sowas hatte ich zumindest in meinem c-kurs damals.
 
ja, genau das meinte ich.

wenn der speicher aber noch belegt bleibt, wie kann ich dann feststellen ob meine speicherfreigabe überhaupt funktioniert hat? wie kann ich das testen?
 
ja das ist so richtig. in c wird speicher nicht beim initialisieren oder freigeben überschrieben. wenn du den zeiger auf dein array mit free() freigibst, dann kannst du danach eigentlich den zeiger auf null abprüfen.

if ( ptr != null )
{
/* wenner hier ist, ist der speicher nicht freigegeben worden */
}

ich kann da jetzt zwar nichts garantieren, aber so hab ich es gelernt. sollte ich mich irren überprüf ich das gleich nochmal.
 
er bleibt ja nicht wirklich belegt, er wird nur nicht überschrieben. und eigentlich solltest du dich darauf verlassen können, dass der speicher freigegeben wird, wenn du das freigeben auch entsprechend aufgerufen hast.
 
nein darauf kann man sich nciht verlassen! deshalb sollte er mit free() freigegeben werden und der pointer auf den speicherbereich einfach auf null geprüft werden. wenn der speicher korrekt freigegeben wurde, ist dieser pointer ein null-pointer, wenn etwas schief ging nicht!

/edit:
selbst beim allokieren des speichers musst du immer überprüfen, ob der speicher auch korrekt allokiert wurde. da du sonst ganz schnell probleme bekommst!
 
also mein array heisst c. ich gebe es so frei:
c = realloc (c, sizeof (c));

dann frage ich es so ab:
if (c !=null)
{
printf (" c wurde nicht freigegeben ");
}
else
{
printf (" c wurde freigegeben ");
}


fehlermeldung: null undeclared
hmmm...
 
Versuch doch mal "if(c!=NULL)" .

edit:
Und poste doch mal deinen ganzen Code, vermutlich hast du noch mehr Fehler, da wenn du zB. ein int Array für 10 Werte mit " int* c = (int *)calloc(10, sizeof(int)); " allokierst, kannst du es mit "c = (int *)realloc(c,20*sizeof(int));" vergrößern und dann mit free(c) wieder freigeben. Und nach jeder dieser Operationen mit if(c==NULL) prüfen obs geklappt hat oder nicht.

Du versuchst es mit realloc freizugeben?!
 
ok:

allerdings muss ich wohl noch was erklären:
das komplette programm soll ein array haben, das immer soviel speicherplatz in ansproch nimmt, wie gerade erforderlich ist. dieses array heisst b.
wenn es vergrößert werden soll, wird der inhalt erst in ein weiteres array c kopiert werden. b wird dann gelöscht, und in neuer größe angelegt. der inhalt von c dann nach b zurückkopiert, und c dann wieder gelöscht. soweit die theorie ;-)

#include <stdio.h>
#include <stdlib.h>

int main()
{
char a;
char* b;
char* c;
int r;
int k;
int j;
int l;
int m;

b = calloc ((1), sizeof(b));


for (r=0; r<10; r=r+1)
{



//Eingabe des Chars und Speicher für c anfrodern
a = getchar ();
k = r + 1;
c = calloc ((k), sizeof(c));


//b nach c kopieren
for (l=0; l<=k; l++)
{
c[l] = b[l];
}

//b löschen
b = realloc (b, sizeof (b));

//b in neuer länge wieder anlegen
b = calloc ((k), sizeof(b));


//c in neues b kopieren
for (m=0; m<=k; m++)
{
b[m] = c[m];
}

//c löschen
c = realloc (c, sizeof (c));

if(c!=NULL)
{
printf (" c wurde nicht freigegeben ");
}
else
{
printf (" c wurde freigegeben ");
}


//neues b jetzt zuweisen:
b[r] = a;


}

printf("\n");
for (j=0; j<10; j++)
{
printf ("%c",b[j]);
}

system("PAUSE");
return 0;

}
 
wie gesagt, nach jedem malloc, calloc, realloc und free kannst du den pointer auf null oder NULL (weiss grad nicht welches) überprüfen und findest damit raus, ob fehler aufgetreten sind

und definitv sollte noch ans ende des programms ein free(b) und free(c) da der speicher unter c nicht automatisch freigegeben wird
 
so wie ich es sehe (kein C Anhänger ;) ), hast Du einen Speicherleck
"man realloc" ergibt:
The realloc() function tries to change the size of the allocation pointed
to by ptr to size, and return ptr. If there is not enough room to
enlarge the memory allocation pointed to by ptr, realloc() creates a new
allocation, copies as much of the old data pointed to by ptr as will fit
to the new allocation, frees the old allocation, and returns a pointer to
the allocated memory. realloc() returns a NULL pointer if there is an
error, and the allocation pointed to by ptr is still valid.
d.h
Code:
/b in neuer länge wieder anlegen
b = calloc ((k), sizeof(b));
ist nicht nur unnötig, sondern der "Verursacher" des Speicherlecks. Realloc "expandiert" schon Deinen Speicher auf die erforderliche Größe und gibt einen Pointer darauf zurück (dabei werden Daten umkopiert, falls erforderlich und der alte Speicherplatz freigegeben).

Allerdings sind da noch andere Fehler vorhanden:
Code:
 for (l=0; l<=k; l++)
{
c[l] = b[l];
}
Ich sehe z.B hier keine vorhergehende initialisierung von k (hint: wir haben CODE-Tags für Quellcode ;) )
Als Tipp: gut bewährt als "Eigenspeicherverwaltung" hat sich die Verdoppelung des Speicherblocks bei unzureichender Größe. Ansonsten entseht zuviel Overhead (dasselbe gilt auch für "kleinere" Speicherblöcke - z.B bei calloc(1,char) werden intern auf jedenfall einige DWORDs "verschwendet" (interne Speicherverwaltung).
Außerdem werden afaik unter Windows 8 oder 16-Byteblöcke reserviert (hat etwas mit Aligning und Speicherverwaltung zu tun), die letzte Aussage ist allerdings nur mit Vorsich zu genießen (länger her, dass ich die Speicherverwaltung betrachtet habe).
 
also ich habe jetzt das mit dem realloc raus, und dafür free (); rein.
außerdem den fehler mit dem k beseitigt.
die abfrage ob c dann frei ist, wird immer noch mit nein beantwortet...

Code:
#include <stdio.h>
#include <stdlib.h>

int main()
{
char a;
char* b;
char* c;
int r;
int k;
int j;
int l;
int m;

b = calloc ((1), sizeof(b));


for (r=0; r<10; r=r+1)
{



//Eingabe des Chars und Speicher für c anfrodern
a = getchar ();
k = r + 1;
c = calloc ((r), sizeof(c));


//b nach c kopieren
for (l=0; l<=r; l++)
{
c[l] = b[l];
}

//b löschen
free (b);

//b in neuer länge wieder anlegen
b = calloc ((r), sizeof(b));


//c in neues b kopieren
for (m=0; m<=k; m++)
{
b[m] = c[m];
}

//c löschen
free (c);

if(c!=NULL)
{
printf (" c wurde nicht freigegeben ");
}
else
{
printf (" c wurde freigegeben ");
}


//neues b jetzt zuweisen:
b[r] = a;


}

printf("n");
for (j=0; j<10; j++)
{
printf ("%c",b[j]);
}

system("PAUSE");
return 0;

}
 
die abfrage ob c dann frei ist, wird immer noch mit nein beantwortet...
Wenn man Speicher mit free() freigibt wird der Speicherverwaltung mitgeteilt,dass sie ihn wieder für etwas anderes verwenden kann. Von "löschen" ist nicht die Rede.

Ist ein Pointer NULL bedeutet das nicht das der Speicher auf dem gezeigt wird freigegeben wurde. Dazu benötigt man eine automatische Speicherbereinigung, was C nicht hat. Die Abfrage nach NULL nach free() würde also bei einem fehlerhaften free() nichts aussagen.
(Normalerweise wird sowas nicht hinterfragt) AUSSERDEM ARBEITET FREE() SO NICHT

wie gesagt, nach jedem malloc, calloc, realloc und free kannst du den pointer auf null oder NULL (weiss grad nicht welches) überprüfen und findest damit raus, ob fehler aufgetreten sind
STIMMT AO NICHT!
malloc, calloc, realloc: gibt Pointer auf neuen Speicherbereich zurück
free: gibt nichts zurück und setzt auch nichts auf NULL. Darum funktioniert die Abfrage auch nicht!

Die einzige Methode sicher zu sein ist den Speicherbereich zu beobachten(Adresse speichern), viel Speicher allozieren und warten bis der oben freigegebene verwendet wird.

Du verwendest calloc auch falsch.
b = calloc ((1), sizeof(b));
entspricht b = calloc ((1), 4) da b ein Pointer auf char ist, also als Pointer die Größe 4 Byte hat. Die allozierst 4 Bytes!! char braucht aber ein Feld von 1Byte Speciherplätzen !
Also b = (char*) calloc(1,sizeof(char))
Man muss auch immer expliziten cast nach malloc/callcoc machen!!!!
 
Zurück
Oben