malloc reagiert unerwartet
-
Moin Moin
erst mal ein Hallo an alle hier. Ich bringe mir gerade C bei und bin jetzt bei
Zeigern etc...Also habe ich mir jetzt mal selbst ein Lernprogramm geschrieben das mir zeigen
soll, wie man es macht und wie man es nicht machen sollte.als schlechts Beispiel habe ich lokal in einer Funktion eine variable
erstellt und dann einen Zeiger ans Hauptprogramm zurückgegeben, mit
dem ich den Wert der Variablen auslesen lassen kann.Das klappt natürlich nur, solange der Speicher noch nicht beansprucht wurde.
Um das zu demonstrieren wollte ich den Arbeitsspeicher einmal vollschreiben
und wieder leeren. Dabei hängt sich das Programm allerdings auf.ich benutze folgenden Code:
char *p; while(p = malloc(32)) { if(NULL == p) { printf("Speicherplatzmangel!!\n"); } } free(p);
Die Reaktion ist jetzt folgende:
erst wird der Arbeitsspeicher vollgeschrieben (laut Taskmanager). Dann bleibt der entweder voll bis ich die konsole schließe oder aber der leert sich wieder.
allerdings wird nie "Speicherplatzmangel" ausgegeben. Das verstehe ich nicht so
ganz.€dit: Außerdem scheint mir, dass free(p); nicht funktioniert.
ich habe den Code erweitert in:
char *p; while(p = malloc(32)) { if(NULL == p) { printf("Speicherplatzmangel!!\n"); } } free(p); long i=0; while(i<100000) { printf("abc"); i++;}
dabei müsste ja der speicher wieder leer werden, während oder bevor die ganz vielen Zeichen ausgegeben werden. Das passiert aber nicht. Der speicher wird
erst nach beenden des Programmes wieder leer (zumindest laut taskmanager)Grüße
Martin
-
moinsen,
warte lange genug, bis auch die auslagerungsdatei voll istzu den zeigern:
p = malloc(32); // p hat adresse xyz
p = malloc (32); // p hat adresse xyz + 32
p = malloc (32); // p hat adresse xyz + 32 + 32free(p); // speicher an position adresse xyz + 32 + 32 wurde freigegeben.
die anderen beiden speicherplätze sind nicht mehr zugänglich.
-
ahhh das macht sinn... weil ich hab noch weiter getestet. wenn ich das free(p) in die schleife schreibe, dann bleibt der arbeitsspeicher leer. Nur die fehlende Ausgabe wundert mich weil der müsste doch entweder immer weiter in der schleife bleiben (was er aber nicht tut, danach kommen noch ausgaben) oder aber er müsste an der ausgabe vorbeikommen... oder denk ich da irgendwie falsch?
bzw... wenn ich mir die schleife noch mal so angucke ... interpretiert das while eventuell NULL als false? weil dann würde der ja nicht mehr reingehen.. also auch keine abfrage
wie mach ich denn dann am besten ne funktion die den speicher vollschreibt und wieder leer macht? (beschäftige mich ers seit 2 Tagen mit C).
Grüße
Martin
-
Martin Leurs schrieb:
erst wird der Arbeitsspeicher vollgeschrieben (laut Taskmanager). Dann bleibt der entweder voll bis ich die konsole schließe oder aber der leert sich wieder.
allerdings wird nie "Speicherplatzmangel" ausgegeben.Da spielt Dir der Speichermanager des Betriebssystems einen Streich. Du mußt via malloc Speicher anfordern und den Speicher auch benutzen (irgendwas reinschreiben).
-
ne es reichte doch die schleife umzuschreiben in
while(p != NULL) { p = malloc(32); if(NULL == p) { printf("Speicherplatzmangel!!\n"); }
dadurch durchläuft der den rest der schleife noch wenn p = NULL ist. Ich hatte
die schleife aus nem Beispiel und scheinbar war die nicht durchdacht und nur
zum angucken nich zum testenich denk ich werd das füllen und wieder leeren mal rekursiv versuchen.
(is ja auch eigentlich keine wichtige funktion^^ nur so zur spielerei)Grüße
Martin
-
So mein rekursiver Ansatz hängt sich ziemlich direkt auf
So sieht die Funktion aus:
void speicher_fuellen() { char *p; p = malloc(32); if(p != NULL) { speicher_fuellen(); } else { printf("Speicherplatzmangel!!\n"); } free(p); }
Das programm hängt sich irgendwo in der Funktion auf. Er baut die Rekursion zwar bis zu einer gewissen Tiefe auf aber dann crasht er. Brauch ich da ein "sleep()" oder ähnliches um den pc nich zu überfordern? ich hab keine ahnung
grüße
Martin
-
Da ist wegen der Funktionsaufrufe wohl schnell der Stack voll, lange bevor malloc den Speicher verbraucht hat.
-
Er baut die Rekursion zwar bis zu einer gewissen Tiefe auf aber dann crasht er. Brauch ich da ein "sleep()" oder ähnliches um den pc nich zu überfordern? ich hab keine ahnung
Eine interessante Frage. Ich hab leider keine Ahnung. Aber ich hab schon öfter davon gehört, dass C seltsam reagiert, wenn bei Rekursionen der Platz ausgeht. Der Ansatz sieht aber sinnvoll aus.
Ich kann dir nur raten, den Stack mit den Zeigern selbst zu machen, und die Rekursion wegzulassen.
-
mngbd schrieb:
Eine interessante Frage. Ich hab leider keine Ahnung. Aber ich hab schon öfter davon gehört, dass C seltsam reagiert, wenn bei Rekursionen der Platz ausgeht.
naja, C kann nichts dafür. C als programmiersprache kennt zwar, rekursion aber keine stacks. was bei einem stacküberlauf passiert, ist systemabhängig. es können speicherbereiche überschrieben werden, die nicht zum stack gehören, oder der stackpointer landet am anderen ende des stacks, oder das system erkennt den fehler und springt in eine ausnahmebhandlung, oder, oder, ...
-
-
ahhh ok von java war ich gewöhnt, dass dann ein fehler stack overflow ausgegeben wurde.... ich muss noch ein wenig davon weg kommen
dann werd ich mal versuchen direkt alle zeiger zu speichern die malloc nutzt (ne liste wär dafür wohl nich schlecht) und dann werd ich die liste nachher durchgehen und den speicher wieder freigeben....
Grüße
Martin