MallocIn informatica, malloc (derivato dai termini memory allocation) è una funzione della libreria standard dei linguaggi di programmazione C e C++ per l'allocazione dinamica della memoria. ConcettiNel linguaggio di programmazione C la memoria può essere gestita staticamente, automaticamente o dinamicamente. Nella gestione statica le variabili sono allocate in una posizione fissa che persiste fino alla fine del programma; in quella automatica sono allocate nello stack e vengono inserite e rimosse in funzione delle chiamate e dei ritorni di funzione. Nell'allocazione automatica la dimensione è richiesta durante il periodo di compilazione come costante. Se la dimensione non è nota durante il periodo di esecuzione (per esempio, se i dati devono essere inseriti via via da tastiera), questo metodo diventa inadeguato. Questa regola tradizionale (necessità di dimensione al momento della compilazione) era vera per C89/90, ed è ancora vera per gli array di dimensione fissa. Tuttavia, gli array di lunghezza variabile (VLA), struttura dati array la cui lunghezza è determinata in fase di esecuzione (invece che in fase di compilazione), sono stati introdotti in C99 come eccezione speciale a questa regola.[1] La durata dell'allocazione della memoria è un'altra fonte di preoccupazione. Né l'allocazione statica né quella automatica sono sufficienti per tutte le situazioni. In quella automatica i dati possono non persistere per più chiamate di funzione, mentre quella statica persiste per tutta la durata del programma sia nel caso in cui sia necessaria, sia in quello in cui non sia più utile. In molte situazioni il programmatore necessita di una maggiore flessibilità nella gestione del ciclo di vita della memoria allocata. Queste limitazioni sono evitabili utilizzando l'allocazione dinamica della memoria, la quale è più esplicita (ma più flessibile), ed è gestita, in genere, mediante l'allocazione nell'heap. Il programma accede a questo blocco di memoria tramite un puntatore che la malloc restituisce. Quando non è più necessaria, la memoria può essere deallocata tramite la funzione free() in modo che possa essere utilizzata per altri scopi. Alcune piattaforme forniscono delle chiamate alla libreria che permettono l'allocazione dinamica in run-time (durante l'esecuzione del programma) dallo stack piuttosto che dall'heap (per esempio glibc's Allocazione dinamica della memoria in CLa funzione void *malloc(size_t size);
Che alloca La memoria allocata tramite void free(void* pointer);
Che rilascia il blocco di memoria indicato da Esempi di utilizzoIl metodo standard per creare un array di dieci interi: int array[10];
Tuttavia, se si vuole assegnare un simile array in modo dinamico, si può utilizzare il seguente codice: /* Alloca spazio per un array con 10 elementi di tipo int. */
int *ptr = (int *)malloc(10 * sizeof (int));
if (!ptr)
{
/* La memoria non può essere allocata, il programma dovrebbe gestire l'errore in modo appropriato. */
} else
{
/* Allocazione avvenuta con successo. Prosegui con il programma. */
free(ptr); /* Abbiamo finito di lavorare con l'array, e liberiamo il puntatore associato. */
ptr = NULL; /* Il puntatore non può essere più usato fino ad un riassegnamento effettuato con malloc. */
}
Si può notare che a volte il codice restituito da int *ptr = (int*)malloc(10 * sizeof (int));
Ma questa è una cattiva pratica: è ridondante sotto lo standard C, come osservato in precedenza; e inoltre, il cast maschera l'eventuale mancata inclusione dell'header Un utile idioma con la int *ptr = malloc(10 * sizeof (*ptr));
Ciò significa che, invece di scrivere un tipo hard-wired all'interno dell'argomento della Funzioni collegateCalloc
void *calloc(size_t nelements, size_t elementSize);
che alloca un'area di memoria, la inizializza a 0, di dimensioni ReallocSpesso è utile che un blocco di memoria possa crescere o ridursi. Questo può essere fatto utilizzando void *realloc(void *pointer, size_t size);
la funzione void *p = malloc(42);
void *p = realloc(NULL, 42); /* equivalent */
Nello standard C89, realloc con dimensione 0 era uguale ad una chiamata a free(). Nello standard C99, non è stata mantenuta questa possibilità; ora, il blocco viene riallocato con una dimensione di zero byte ed è restituito un puntatore diverso da null (che non può essere direttamente dereferenziato, dato che non punta a nessuna area di memoria allocata, ma potrà essere usata per una futura chiamata a realloc o free). Si deve sempre utilizzare una variabile temporanea. Ad esempio: void *p = malloc(orig_size);
/* e dopo... */
void *tmp = realloc(p, big_size);
if (tmp != NULL) {
p = tmp; /* OK, nuovo assegnamento, più grande di p */
} else {
/* gestire il problema in qualche modo */
}
Se invece uno ha void *p = malloc(orig_size);
/* e dopo... */
p = realloc(p, big_size);
nel caso in cui non sia possibile ottenere Errori comuniL'uso improprio della Allocazione fallita
Memory leakQuando chiami una void *ptr;
size_t size = BUFSIZ;
ptr = malloc(size);
/* qui avvengono ulteriori operazioni... */
/* ora la dimensione del buffer deve essere raddoppiata */
if (size > SIZE_MAX / 2) {
/* errore di overflow */
/* ... */
return (1);
}
size *= 2;
ptr = realloc(ptr, size);
if (ptr == NULL) {
/* la realloc fallisce (e restituisce un puntatore null), ma il puntatore originale ptr è andato perduto
quindi la memoria non può essere liberata e avviene una perdita di memoria */
/* ... */
return 1;
}
/* ... */
Utilizzo dopo free()Dopo che un puntatore è passato per una funzione int *ptr = (int*)malloc(sizeof (int));
free(ptr);
*ptr = 0; /* comportamento indefinito */
Il codice avrà un comportamento i cui effetti possono variare. Anche il tentativo di stampare la variabile printf ha un effetto indefinito (assumendo che printf("%p", (void *) ptr); /* comportamento indefinito */
Comunemente, il sistema può riutilizzare la memoria liberata per altri scopi. Pertanto, la scrittura in memoria verso un puntatore ad una regione deallocata, può avere come risultato una sovrascrittura di altri dati del programma stesso. A seconda del tipo di dati che vengono sovrascritti, questo può causare la corruzione dei dati stessi e un successivo crash del programma. Un cattivo esempio del tentativo di risolvere questo problema può essere il doppio passaggio tramite free(ptr);
ptr = NULL; /*è sicuro (butta via la locazione del puntatore).*/
Questa funzione è sicura e non provoca anomalie,[6] tuttavia, anche questo accorgimento non riesce a proteggere da altri usi impropri dello stesso puntatore doppiamente liberato. La prassi migliore è quella di passare fuori dallo scope (o visibilità) immediatamente dopo aver liberato la memoria. Liberare memoria non allocataUn altro problema può sopraggiungere passando un puntatore a char *msg = "Messaggio predefinito";
int tbl[100];
Il passaggio di entrambi i puntatori a Limite spazio di allocazioneIl blocco di memoria più grande possibile che Note
Voci correlate
Collegamenti esterni
|
Portal di Ensiklopedia Dunia