Pagina 1 di 1

[C] free

Inviato: lun 2 giu 2008, 15:31
da Dani
La memoria allocata con malloc/calloc/realloc quando viene liberata con free è immediatamente riutilizzabile dal sistema operativo ?
Ho una funzione che alloca diversi megabytes con malloc e prima di ritornare il controllo alla funzione chiamante libera il tutto. Il problema è che questo non sembra accadere !
Ho messo un getchar() subito dopo i free(), aperto un terminale con un "free -m -s .4" in loop e noto sorprendentemente che la memoria non risulta libera finchè il programma non viene terminato !?
Com'è possibile questo considerando che il programma non ha memory leak ?
Credo di essermi perso qualcosa :|

Re: [C] free

Inviato: lun 2 giu 2008, 16:03
da Mario Vanoni
Dani ha scritto:La memoria allocata con malloc/calloc/realloc quando viene liberata con free è immediatamente riutilizzabile dal sistema operativo ?
Ho una funzione che alloca diversi megabytes con malloc e prima di ritornare il controllo alla funzione chiamante libera il tutto. Il problema è che questo non sembra accadere !
Ho messo un getchar() subito dopo i free(), aperto un terminale con un "free -m -s .4" in loop e noto sorprendentemente che la memoria non risulta libera finchè il programma non viene terminato !?
Com'è possibile questo considerando che il programma non ha memory leak ?
Credo di essermi perso qualcosa :|
Vecchia discussione,
UNIX/Linux usa fino all'esaurimento tutta la memoria a disposizione,
free(3) libera quella del tuo programma, ma non la totale.

Re: [C] free

Inviato: lun 2 giu 2008, 16:23
da Dani
E io quella del mio programma voglio liberare !

1) free -m | grep "cache:" | awk '{print $3'} dice 226
2) avvio il programma
3) free dice sempre 226
4) viene chiamata una funzione che alloca della memoria, facciamo 10 mega
5) free dice 236
6) la funzione che ha allocato la memoria finisce di lavorare, chiama free() per ogni malloc/calloc/realloc e ritorna
7) free vede ancora 236 mega occupati
8) il programma termina
9) free ora dice 226 ...

Idem con top,
$ top -d 0.5 -p `pidof programma`

Dal momento dell'allocazione alla terminazione del programma vede sempre una percentuale costante di memoria usata, in pratica e' come se le chiamate a free() non avessero effetto !

Re: [C] free

Inviato: lun 2 giu 2008, 16:29
da robbybby
Se allochi, per esempio, 10 byte (malloc(10)), la malloc non chiede 10 byte al sistema operativo, ma ne chiede di piu' (per esempio una pagina, che su i386 e Linux e' 4k). Questo per evitare un'eccessiva frammentazione dell'heap, e un rallentamento del programma.
Al successivo malloc di pochi byte, il tuo programma non richiedera' la memoria al Sitema Operativo, ma ne utilizzera' un altro po' di quella allocata in precedenza.
Questo per allocazioni piccole.

Re: [C] free

Inviato: lun 2 giu 2008, 17:44
da Mario Vanoni
Da un vecchio libro C del 1987, quindi UNIX:

voce free

although your program will never get smaller using free -
that is, free will not "shrink" the size of a process

finche' c'e` memoria, il tuo programma rimane in memoria,
qualora tu lo richiamassi per essere subito disponibile

questo e` normalissimo per UNIX, e quindi per Linux

mettiti il cuore in pace, dei 4GB sulla mia macchina,
guardando top, rimangono forse 33M free, poi risale a 130M

test: cd / ; find -exec wc {} \;

Ctrl-C per terminare, top: 130M free

rifatto il test sopra: rimane sempre sui 130M free

Re: [C] free

Inviato: lun 2 giu 2008, 18:06
da Dani
E cosa accade alla memoria bufferizzata qualora un nuovo processo desideri allocarne altra per se ?

Ad esempio su una macchina con 32 mb di ram totale il processo x alloca 20 mega di memoria, li libera con free() ma resta in esecuzione. Un nuovo processo y necessita di altri 20 mega, ma stando all'output del comando free non ci sono risorse sufficienti. Che succede in questo caso, le risorse bufferizzate vengono spazzate via o il kernel inizia ad usare lo swap ? Mi auguro la prima :lol:

Re: [C] free

Inviato: mar 3 giu 2008, 15:03
da Mario Vanoni
Dani ha scritto:E cosa accade alla memoria bufferizzata qualora un nuovo processo desideri allocarne altra per se ?

Ad esempio su una macchina con 32 mb di ram totale il processo x alloca 20 mega di memoria, li libera con free() ma resta in esecuzione. Un nuovo processo y necessita di altri 20 mega, ma stando all'output del comando free non ci sono risorse sufficienti. Che succede in questo caso, le risorse bufferizzate vengono spazzate via o il kernel inizia ad usare lo swap ? Mi auguro la prima :lol:
Come detto, UNIX usa tutta la memoria disponibile.
Se allocata, poi liberata con free, rimane li`.
La ripetizione di un programma impiega meno tempo!
Se un altro processo richiede memoria, usera` quella liberata,
se non ne trova piu`, entrera` il famigerato OOM killer.

Esempio pratico, puoi usare il tuo programma per testare:

- cd /zz/src
- du -hs dice 19GB

- macchina (ab)usata, top dice 4GB used, 130M free
- time (built-in) o /usr/bin/time (con le opzioni -p -a -o /path/file) ls -alR > /dev/null
- la prima volta 1m5..., top 19MB free
- ripetuto dieci volte, ora sempre 0m5..., top sale a 39M free

- stessa macchina dopo reboot, top dice 180M used, 3.9GB free
- time (built-in) o /usr/bin/time (con le opzioni -p -a -o /path/file) ls -alR > /dev/null
- la prima volta 1m5..., top 590MB used, 3.5GB free
- ripetuto dieci volte, ora sempre 0m5..., top scende a 355M free

Re: [C] free

Inviato: mar 3 giu 2008, 22:09
da robbybby
Con il seguente programmino, usando top per controllare quanta memoria il tuo programma usa, vedi che malloc alloca la ram, e free la dealloca SUBITO, e non al termine del programma.
Se non metto il memset(), cioe' se non uso la memoria allocata con malloc() la memoria in realta' non viene occupata.

Codice: Seleziona tutto

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

#define CNT 90000000

int main()
{
int *pi = 0;
int i = 0;

  puts("1\n");
  scanf("%i",
            &i);

  pi = malloc(CNT * sizeof(int));
  printf("Pointer: %x\n",
            pi);
  memset(pi,
                0,
               sizeof(int) * CNT);

  puts("2\n");
  scanf("%i",
            &i);

  free(pi);

  puts("3\n");
  scanf("%i",
            &i);

  return 0;
}