Ich habe noch mal schnell ein kleines Testprogrämmchen geschrieben um zu überprüfen ob ich die Doku richtig verstanden habe.
Folgendes:
Code:
#include <stdio.h>
#include <stdlib.h>
int main() {
const int len = 1024*1024;
void **a = (void**)malloc(len*sizeof(void*));
int i;
for (i = 0; i < len; i++)
a[i] = (void*)malloc(1024);
void* blocker = malloc(100);
printf("malloced 1GB\n");
getchar();
for (i = 0; i < len; i++)
free(a[i]);
printf("freed 1 GB\n");
getchar();
free(blocker);
printf("freed blocker\n");
getchar();
return 0;
}
a ist ein Pointer-Array. In der For-Schleife werden für die 1024*1024 Pointer in a jeweils 1024 Byte alloziert. Insgesamt 1 GB. Die 1024 Bytes sind jeweils so klein dass mmap nicht benutzt wird.
Nach den mallocs ist der Speicher voll:
Code:
peschmae 6562 4.8 26.4 1076820 1073588 pts/5 S+ 13:20 0:00 ./test
In einem nächsten Schritt werden weitere 100 Bytes alloziert - die sind (offenbar) zuoberst auf dem Heap. Anschliessend werden die 1 GB Speicher die zu den Pointern in a gehören wieder freigegeben. Nachher ist der Speicher immer noch belegt:
Code:
peschmae 6562 4.6 26.4 1076820 1073592 pts/5 S+ 13:20 0:00 ./test
Was daran liegt dass die oberste Adresse auf dem Heap vom Speicher in blocker belegt ist - die 1 GB darunter sind zwar frei, können aber mit sbrk nicht ans OS zurückgegeben werden weil sbrk nur die Heap-Obergrenze dynamisch verschieben kann.
Das geht erst wenn auch der blocker-Speicher weg ist:
Code:
peschmae 6562 4.3 0.2 11976 8760 pts/5 S+ 13:19 0:01 ./test
Fazit in Bezug auf die Ausgangsfrage: Es scheint als müsstest du sicherstellen dass du wirklich allen Speicher wieder freigibst der oben auf dem Heap ist (d.h. spät alloziiert wurde - wobei der Zusammenhang zwischen spät alloziiert und oben auf dem Heap ja nicht zwingend ist), damit der Speicher wieder ans OS zurückgegeben werden kann.
Oder genug grosse Speicherblöcke benutzen, damit mmap benutzt wird. Oder die Limits ändern dass häufiger mmap benutzt wird (wobei sich dann die Frage stellt ob das nicht plötzlich ineffizient wird - z.B. wegen Verwaltungsaufwand oder ob die Memory-Mapping-Tabellen irgendwo in ihrer Grösse beschränkt sind (läuft das eventuell in Hardware?); irgend einen Grund wird es schon haben dass die Methode normalerweise nur für grössere Speicherblöcke verwendet wird)
Interessanter Kommentar zum Thema: http://c-faq.com/malloc/free2os.es.html
MfG Peschmä
Lesezeichen