Funzione malloc() nella libreria C con EXAMPLE

⚡ Riepilogo intelligente

In C, la funzione malloc() riserva un blocco di memoria sull'heap in fase di esecuzione e restituisce un puntatore void al suo primo byte, consentendo ai programmi di richiedere spazio di memoria la cui dimensione è sconosciuta fino all'effettiva esecuzione del codice.

  • 🧠 Allocazione del tempo di esecuzione: La funzione malloc() riserva memoria durante l'esecuzione quando la dimensione necessaria non è nota in fase di compilazione.
  • 📦 Sintassi: Un puntatore cast_type riceve malloc(byte_size), la cui dimensione viene solitamente definita con sizeof per garantire la portabilità.
  • ⚠️ Controllo NULL: Una richiesta non riuscita restituisce un puntatore NULL, quindi convalida il risultato prima di dereferenziarlo.
  • Aritmetica dei puntatori: Il blocco è contiguo, quindi usa + invece di ++ per accedere agli elementi dell'array.
  • 🧹 Libera la memoria: Rilascia ogni blocco con free() per prevenire perdite di memoria e puntatori pendenti.
  • 🤖 Assistenza AI: Gli assistenti IA e GitHub Copilot redigono le chiamate malloc() e segnalano le istruzioni free() mancanti.

Funzione malloc() in C

Cos'è malloc in C?

La funzione malloc() indica l'allocazione della memoria. È una funzione che viene utilizzata per allocare dinamicamente un blocco di memoria. Riserva lo spazio di memoria della dimensione specificata e restituisce il puntatore nullo che punta alla posizione di memoria. Il puntatore restituito è solitamente di tipo void. Significa che possiamo assegnare la funzione malloc a qualsiasi puntatore.

Cos'è malloc in C

Sintassi

ptr = (cast_type *) malloc (byte_size);

Qui,

  • ptr è un puntatore di cast_type.
  • La funzione malloc restituisce un puntatore alla memoria allocata di byte_size.
Example: ptr = (int *) malloc (50)

Quando questa istruzione viene eseguita con successo, viene riservato uno spazio di memoria di 50 byte. L'indirizzo del primo byte di spazio riservato è assegnato al puntatore ptr di tipo int.

Consideriamo un altro esempio di implementazione di malloc:

#include <stdlib.h>
int main(){
int *ptr;
ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */
    if (ptr != NULL) {
      *(ptr + 5) = 480; /* assign 480 to sixth integer */
      printf("Value of the 6th integer is %d",*(ptr + 5));
    }
}

Produzione:

Value of the 6th integer is 480

Si noti che sizeof(*ptr) è stato utilizzato al posto di sizeof(int) per rendere il codice più robusto nel caso in cui la dichiarazione di *ptr venga successivamente convertita in un tipo di dati diverso.

L'allocazione potrebbe non riuscire se la memoria non è sufficiente. In questo caso restituisce un puntatore NULL. Quindi, dovresti includere il codice per verificare la presenza di un puntatore NULL.

Tieni presente che la memoria allocata è contigua e può essere trattata come un array. Possiamo usare pointer per accedere agli elementi dell'array è necessario utilizzare operazioni aritmetiche anziché le parentesi quadre [ ]. Si consiglia di utilizzare + per fare riferimento agli elementi dell'array perché l'utilizzo degli incrementi ++ o += modifica l'indirizzo memorizzato dal puntatore.

La funzione Malloc può essere utilizzata anche con il tipo di dati carattere e con tipi di dati complessi come le strutture.

Perché usare malloc() in C?

Gli array statici e le variabili ordinarie fissano le loro dimensioni quando il programma viene compilato, il che spreca spazio quando il requisito risulta inferiore e fallisce completamente quando risulta superiore. malloc() risolve questo problema richiedendo memoria in fase di esecuzione, in modo che un programma possa dimensionare un buffer in base alla quantità esatta di dati che riceve. Questa flessibilità in fase di esecuzione è il cuore di allocazione dinamica della memoria in c.

L'allocazione dinamica con malloc() è la scelta giusta in diverse situazioni comuni:

  • La quantità di dati in ingresso è sconosciuta fino all'esecuzione del programma, ad esempio durante la lettura di un file o di un elenco fornito dall'utente.
  • Sono necessari blocchi di grandi dimensioni che andrebbero a sovraccaricare lo stack limitato, poiché malloc() attinge dall'heap, che è molto più grande.
  • I dati devono sopravvivere alla funzione che li ha creati, perché la memoria heap persiste finché non viene rilasciata esplicitamente.
  • Le strutture e gli array devono potersi espandere o ridurre durante l'esecuzione del programma.

Poiché il blocco riservato viene restituito come puntatore, può essere passato tra funzioni in modo efficiente senza copiare i dati sottostanti.

Come liberare la memoria allocata da malloc()

La memoria riservata dalla funzione malloc() risiede nell'heap e non viene mai rilasciata automaticamente. Quando un programma continua ad allocare memoria senza liberarla, consuma gradualmente tutta la memoria disponibile, un difetto noto come perdita di memoria. La funzione free() restituisce al sistema un blocco di memoria libero in modo che lo spazio possa essere riutilizzato.

La funzione free() accetta un singolo argomento, il puntatore restituito da malloc(), e rilascia l'intero blocco in una sola volta:

int *ptr;
ptr = malloc(10 * sizeof(int));
if (ptr != NULL) {
    /* use the allocated memory here */
    free(ptr);   /* release the block */
    ptr = NULL;  /* avoid a dangling pointer */
}

Segui queste regole per gestire la memoria dinamica in modo sicuro:

  • Chiama free() esattamente una volta per ogni malloc() andato a buon fine; liberare lo stesso blocco due volte causa un comportamento indefinito.
  • Imposta il puntatore a NULL dopo averlo liberato, in modo che non possa essere riutilizzato come puntatore pendente.
  • Non liberare mai con free() un puntatore che malloc() non ha restituito, incluso un puntatore spostato tramite aritmetica dei puntatori.
  • Ogni allocazione deve essere associata a una release corrispondente prima che il puntatore esca dall'ambito di validità.

Keeping L'allocazione e il rilascio bilanciati sono la disciplina fondamentale della gestione manuale della memoria in C e prevengono sia le perdite di memoria che i crash causati dal riutilizzo della memoria liberata.

malloc() vs calloc(): differenze chiave

malloc() e calloc() Entrambe riservano memoria heap, ma differiscono negli argomenti e nel modo in cui trattano il nuovo blocco. malloc() accetta un argomento, il numero totale di byte, e lascia il contenuto non inizializzato, quindi il blocco contiene valori casuali imprevedibili finché il programma non vi scrive. calloc() accetta due argomenti, il numero di elementi e la dimensione di ciascuno, e azzera ogni byte prima di restituire il puntatore.

Le differenze pratiche si riducono a tre punti:

  • Inizializzazione: calloc() azzera la memoria, mentre malloc() non lo fa, il che rende malloc() leggermente più veloce quando i valori verranno comunque sovrascritti.
  • Argomenti: si scrive malloc(n * size) ma calloc(n, size) per riservare lo stesso array.
  • Caso d'uso: scegliere calloc() quando è importante avere un blocco pulito e inizializzato a zero, e malloc() quando si preferisce la velocità e l'inizializzazione viene gestita manualmente.

Entrambe le funzioni sono dichiarate in stdlib.h, entrambe restituiscono un puntatore void o NULL in caso di errore ed entrambe restituiscono la memoria con la stessa funzione free().

DOMANDE FREQUENTI

In C il cast è facoltativo e spesso sconsigliato, perché void* si converte automaticamente in qualsiasi puntatore a oggetto e un cast esplicito può mascherare un'inclusione mancante di stdlib.h. In C++, tuttavia, è necessario il cast.

Un valore di ritorno NULL indica che la richiesta non è andata a buon fine, solitamente a causa di memoria insufficiente. Controllare sempre il puntatore prima di utilizzarlo, poiché dereferenziare NULL porta a un comportamento indefinito e in genere causa l'arresto anomalo del programma.

realloc() ridimensiona un blocco precedentemente riservato da malloc(), keeping dati esistenti fino alla dimensione più piccola. In caso di errore, restituisce NULL e lascia intatto il blocco originale, quindi assegna prima il risultato a un puntatore temporaneo.

Si verifica una perdita di memoria quando la memoria allocata dall'heap tramite la funzione malloc() non viene mai rilasciata con la funzione free(). Il programma continua a riservare spazio che non utilizza più, il che può gradualmente esaurire la memoria disponibile.

La funzione malloc() riserva memoria nell'heap, non nello stack. I blocchi di memoria nell'heap rimangono validi fino alla chiamata di free(), quindi possono sopravvivere alla funzione che li ha creati, a differenza delle variabili automatiche nello stack che scompaiono al termine dell'esecuzione.

malloc() è una funzione di libreria che restituisce void* e necessita di sizeof per calcolare i byte. C++ `new` è un operatore che restituisce un puntatore tipizzato e chiama i costruttori. Abbina `malloc()` a `free()` e `new` a `delete`.

Sì. Gli assistenti di programmazione basati sull'IA generano automaticamente le chiamate a malloc(), inseriscono controlli per i valori NULL e segnalano le chiamate a free() mancanti o le perdite di memoria, e possono anche spiegare l'aritmetica dei puntatori. Compila e testa sempre il codice generato prima di fidarti.

Copilota GitHub suggerisce le righe malloc(), sizeof() e free() corrispondenti da un commento che descrive il tuo intento. RevPrima di compilare, esamina attentamente ogni suggerimento relativo ai controlli NULL mancanti e alle perdite di memoria.

Riassumi questo post con: