0Pricing
C Academy · Lezione

Rilevare le perdite

Basi di memcheck

Rilevare le perdite è una lezione C Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C Academy include 4 lezioni in totale.

Che cos'è una perdita

Una perdita di memoria si verifica quando alloca memoria nell'heap con malloc, calloc o realloc e perde ogni puntatore a essa prima di chiamare free.

Il blocco rimane riservato ma irraggiungibile fino all'uscita del processo. Nei programmi a esecuzione prolungata, le perdite si accumulano finché la memoria non si esaurisce.

Una perdita minimale

Questo programma perde un blocco di 40 byte.

Il puntatore p è una variabile locale. Quando main restituisce il controllo, p scompare, ma il blocco dell'heap a cui puntava non viene mai liberato.

#include <stdlib.h>

int main(void) {
    int *p = malloc(10 * sizeof(int));
    p[0] = 1;
    return 0; /* never free(p) */
}

Eseguire memcheck

memcheck è lo strumento predefinito, quindi può omettere il nome dello strumento.

Aggiunga --leak-check=full per ottenere una traccia dello stack per ogni allocazione persa.

gcc -g -O0 -o leak leak.c
valgrind --leak-check=full ./leak

Il riepilogo delle perdite

All'uscita, Valgrind stampa un LEAK SUMMARY. Per il programma precedente, il risultato è approssimativamente:

definitely lost: 40 bytes in 1 blocks

La traccia indica il punto esatto della chiamata a malloc, così può sapere con precisione quale allocazione non è mai stata liberata.

Le quattro categorie di perdite

memcheck suddivide la memoria persa in quattro categorie:

  • definitely lost — non rimane alcun puntatore; è una vera perdita
  • indirectly lost — è raggiungibile solo attraverso un blocco classificato come definitivamente perso
  • possibly lost — rimane solo un puntatore interno
  • still reachable — all'uscita esiste un puntatore, ma non è mai stata effettuata la deallocazione

Definitivamente persa e ancora raggiungibile

definitely lost è la categoria urgente: quei byte non possono più essere recuperati mentre il programma è in esecuzione.

still reachable è meno grave. Il blocco è perso all'uscita, ma un puntatore globale o statico continua a riferirvisi; di solito si tratta di un'allocazione eseguita una sola volta che semplicemente non ci si è preoccupati di liberare.

Perdite indirette

Quando si perde la testa di una struttura concatenata, ogni nodo diventa irraggiungibile.

La testa viene indicata come definitely lost e il resto come indirectly lost. Risolvendo la causa principale, cioè la testa persa, si recupera tutto.

struct Node { int v; struct Node *next; };

struct Node *make(void) {
    struct Node *h = malloc(sizeof *h);
    h->next = malloc(sizeof *h);
    h->next->next = NULL;
    return h;
}
/* if the caller drops the returned head, both nodes leak */

La versione corretta

Libere ciò che alloca. Questa versione non presenta alcuna perdita.

Con Valgrind, restituisce All heap blocks were freed -- no leaks are possible.

#include <stdlib.h>

int main(void) {
    int *p = malloc(10 * sizeof(int));
    p[0] = 1;
    free(p);
    return 0;
}

Contare le allocazioni

Anche in assenza di perdite, HEAP SUMMARY indica quanto è stato impegnato il programma:

total heap usage: 1 allocs, 1 frees, 40 bytes allocated

Quando il numero di allocazioni e deallocazioni coincide, l'esecuzione è pulita. Una discrepanza è il primo indizio che qualcosa non è stato liberato.

Mostrare i blocchi raggiungibili

Per impostazione predefinita, memcheck non elenca in dettaglio i blocchi still reachable. Per analizzare anche questi, aggiunga:

--show-leak-kinds=all

In questo modo viene prodotta una traccia per ogni categoria, utile quando vuole un programma che liberi assolutamente tutto prima dell'uscita.

valgrind --leak-check=full --show-leak-kinds=all ./leak

Perdite nei percorsi di errore

Le perdite più insidiose si nascondono nei percorsi che restituiscono il controllo in anticipo. In questo caso, se la seconda allocazione non riesce, il primo blocco va perso.

I test ordinari raramente percorrono questi rami, ma memcheck li rileva ogni volta che il percorso viene eseguito. Prima di restituire il controllo in caso di errore, liberi sempre ciò che possiede.

char *a = malloc(100);
char *b = malloc(100);
if (!b) {
    /* bug: a is leaked here */
    return -1;
}
/* fix: free(a); before returning */

Verifica rapida

Scelga la categoria di perdita che richiede l'attenzione più urgente.

Riepilogo

Ora sa rilevare le perdite con memcheck:

  • Esegua valgrind --leak-check=full ./prog su un binario compilato con -g
  • Legga LEAK SUMMARY e HEAP SUMMARY
  • D dia priorità a definitely lost, quindi risalga dalle perdite indirette alla loro radice
  • Usi --show-leak-kinds=all per analizzare i blocchi ancora raggiungibili

Prossimo argomento: accessi non validi alla memoria.

Domande Frequenti

La lezione «Rilevare le perdite» è gratuita?

Sì — il testo completo di «Rilevare le perdite» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C Academy, passa a CoddyKit PRO. Il corso C Academy include 4 lezioni in totale.

Cosa imparerò in «Rilevare le perdite»?

Basi di memcheck Eserciti C Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare C Academy?

Non è richiesta alcuna esperienza precedente. C Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Rilevare le perdite»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione C Academy?

Sì. Ogni lezione C Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Perché usare Valgrind
  2. Rilevare le perdite
  3. Accessi non validi
  4. Leggere i report
← Torna a C Academy