PDA

Visualizza la versione completa : C - malloc


matteolandi
23-07-2004, 18:48
ciao,

se in una funzione alloco memoria per una variabile s con malloc e alla fine restituisco al chiamante il valore di s
come faccio a liberare la memoria allocata?

una cosa del genere mi sembra poco elegante

free(s);
return(s);


grazie

Johnny_Depp
23-07-2004, 18:58
usi una seconda funzione che dealloca la memoria...

alloca();
elabora();
dealloca();

matteolandi
23-07-2004, 19:12
e se creo s all'interno della funzione, è comunque necessario liberare lo spazio allocato? oppure all'uscita dalla funzione termina anche il ciclo di vita della variabile (e quindi lo spazio torna disponibile)?

novantuno
23-07-2004, 19:38
Non penso che sia così, in quanto la variabile non è
stata dichiarata all'interno della funzione e quindi
ha una permanenza statica al contrario di una variabile
locale, che invece ha permanenza automatica (le variabili
vengono distrutte alla fine della funzione) !

Penso che dovrai liberare la memoria occupata dalla
variabile !

Questo è un mio parere !
Io la penso così ! :)

/dev/null
23-07-2004, 20:11
Non proprio:
Anche una variabile locale, che allochi dentro la funzione la devi disallocare (o dentro la funzione, se non serve piu') o all'esterno (se viene utilizzata dalla funzione chiamante, ad esempio facendola ritornare)


:ciauz:

matteolandi
23-07-2004, 20:30
ma se la variabile ritorna per valore alla main, non posso disallocarla nella main... oppure si? la main no ne sa nulla dell'esistenza di questa variabile essendo questa locale ad un'altra funzione

unomichisiada
24-07-2004, 00:32
free(s);
return(s);

Così ti va in crash il programma di sicuro se usi s dopo che la funzione ha ritornato.E' assolutamente sbagliato!

Tieni presente che nel tuo caso specifico tu hai s che è una variabile PUNTATORE, locale alla funzione,ebbene la variabile puntatore ha una durata limitata al tempo di esecuzione ma la memoria allocata con malloc a cui quella variabile PUNTA non viene affatto liberata automaticamente all'uscita.tu ritornando s non fai che creare un nuovo puntatore (il cui nome non è meglio specificato) dello stesso tipo di s e farlo puntare esattamente dove puntava s.In questo modo all'esterno della funzione puoi assegnare il valore di ritorno suddetto ad una variabile puntatore (locale alla funzione chiamante stavolta),chiamiamola t.una volta che hai fatto le tue brave cose con t puoi e devi invocare free(t) altrimenti la memoria nn verrà liberata(quantomeno fino al termine del prog.Claro?

/dev/null
24-07-2004, 00:48
Originariamente inviato da matteolandi
ma se la variabile ritorna per valore alla main, non posso disallocarla nella main... oppure si? la main no ne sa nulla dell'esistenza di questa variabile essendo questa locale ad un'altra funzione Sì, devi liberarla nella main...
La funzione malloc funziona così:
Alloca inizialmente X bytes di dimenzione ssize_t che normalmente -almeno su sistemi a 32 bit- corrisponde a 4 bytes (questo almeno sotto GNU/Linux o su sistemi che utilizzano le GNU C Library: glibc)...
In questi sizeof(ssize_t) bytes scrive la dimensione dei bytes che hai deciso di allocare. Nelle celle di ram successive a alloca tanti bytes quanti ne hai richiesti (e quanti ne sono scritti in quei famosi ssize_t bytes) e restituisce all'utente un puntatore al primo di questi bytes allocati...
Questo programma che rilascio sotto la GPL ( :unz: ) dovrebbe farti capire un po' di piu' quel che ti ho spiegato (funziona sotto GNU/Linux, ma non penso che il tipo di dato ssize_t esista anche sotto altri sistemi):
#include <sys/types.h>
#include <stdio.h>
#include <time.h>

int main( ) {
srand ( (unsigned) time (NULL) );
char * pippo = (char *) malloc ( rand()%(1024*1024*10) );
printf ( "Hai allocato %d bytes\n", *( (ssize_t *) ( pippo - sizeof(ssize_t) ) ) );
free ( pippo );
}* in sys/types.h e' definito il tipo di dato ssize_t


Quando invece tu usi la realloc (da qualunque funzione tu la richiami), va a leggere i sizeof(ssize_t) bytes precedenti al puntatore che gli passi, dove trova la dimensione attuale, e ne cambia il valore con la nuova dimensione che hai richiesto.
Quando usi la free (da qualunque funzione tu la richiami), va a leggere i sizeof(ssize_t) bytes precedenti al puntatore che gli passi, dove trova la dimensione del puntatore, e tramite una system call comunica al kernel che i successivi X bytes (dove X corrisponde al valore letto nei sizeof(ssize_t) bytes precedenti) possono venire deallocati...

In questo modo la funzione realloc e free puoi usarle su qualunque puntatore precedentemente allocato dalla malloc (e teoricamente lo puoi usare anche su puntatori non allocati ***ma che non hai mai mandato a puntatore a qualche indirizzo diverso da 0/NULL***, in quanto, sempre almeno secondo le glibc, un puntatore non allocato dovrebbe puntare a NULL)...


*WARNING*: Non modificare manualmente i 4 bytes precedenti a quelli puntati da un puntatore allocato in quanto puo' succedere del casino:
CASO 1: Nel caso che tu ci scriva un valore maggiore di quello gia' presente, se lo deallochi rischi:
a) di avere un segmentation fault in quanto al kernel potrebbe venire chiesto di deallocare dei bytes non sotto il controllo del processo corrente. Il kernel risponde con un SIGSEGV, se viene gestito o ignorato non succede nulla, altrimenti il processo termina.
b) di perdere alcuni bytes di alcune tue variabili. Questo e' il caso peggiore, e puo' evere centinaia di conseguenze indefinite, imprevedibili, ma tutte sicuramente spiacevoli.
CASO 2: Se ci scrivi un valore minore succede che la differenza di bytes resta allocata fintanto che il processo non termina, inoltre se cerchi poi di usare la realloc specificando una dimensione maggiore di quella scritta in quei sizeof(ssize_t) bytes, la memoria allocata da questo puntatore cambia posizione e non recuperi i vecchi bytes successivi...


*WARNING2* Stai sempre MOLTO attento a non usare la free o la realloc su un puntatore che non punta ad una cella di memoria che e' stata restituita da una funzione malloc, o da una successiva funzione realloc. Altrimenti si verifica quanto descritto in CASO1->b).


Tutto cio' e' vero solo su GNU/Linux o sistemi che utilizzano le glibc, non so niente su altri sistemi...



PS: Amo la programmazione a basso livello... Ma forse l'avevate gia' notato? :stordita:

matteolandi
24-07-2004, 11:43
TNX

adesso è tutto più chiaro

unomichisiada
24-07-2004, 13:38
size_t è definito anche dagli header di windows ed è un semplice int

Loading