0Pricing
C Academy · Lezione

Accessi non validi

Accessi oltre i limiti e dati non inizializzati

Accessi non validi è una lezione C Academy gratuita su CoddyKit. Questa è la lezione 3 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.

Oltre le perdite

Le perdite sprecano memoria, ma i bug di accesso non valido la corrompono. memcheck rileva diversi tipi di accesso:

  • Lettura o scrittura oltre la fine di un buffer
  • Uso della memoria dopo free
  • Lettura di valori non inizializzati
  • Lettura o scrittura tramite un puntatore errato

Questi problemi causano gli arresti anomali più pericolosi e più difficili da riprodurre.

Scrittura oltre i limiti

Questo programma alloca spazio per 5 int, ma scrive all'indice 5, cioè nel sesto elemento.

L'indice 5 si trova un elemento oltre la fine. memcheck segnala una scrittura non valida di dimensione 4 in questa riga.

#include <stdlib.h>

int main(void) {
    int *a = malloc(5 * sizeof(int));
    a[5] = 99; /* valid indices are 0..4 */
    free(a);
    return 0;
}

Leggere l'errore

Il report indica l'operazione, la dimensione e la posizione rispetto al blocco:

Invalid write of size 4
Address 0x... is 0 bytes after a block of size 20 alloc'd

La frase «0 bytes after a block of size 20» indica che l'accesso è avvenuto immediatamente oltre un'allocazione di 20 byte (5 int).

Lettura oltre i limiti

Vengono rilevate anche le letture. In questo caso, il ciclo esegue un'iterazione oltre il necessario.

memcheck segnala una lettura non valida di dimensione 4 nell'ultima iterazione, anche se il programma potrebbe «funzionare» per pura fortuna.

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

int main(void) {
    int *a = calloc(3, sizeof(int));
    for (int i = 0; i <= 3; i++)   /* should be i < 3 */
        printf("%d\n", a[i]);
    free(a);
    return 0;
}

Valori non inizializzati

malloc non azzera la memoria. Usarla prima di assegnarle un valore produce un valore imprevedibile.

memcheck segnala Conditional jump or move depends on uninitialised value(s) quando un valore di questo tipo influenza il flusso di controllo o l'output.

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

int main(void) {
    int *p = malloc(sizeof(int));
    if (*p == 0)              /* *p was never set */
        printf("zero\n");
    free(p);
    return 0;
}

Perché i report sui valori non inizializzati sono ritardati

memcheck non segnala il problema nell'istante in cui si legge memoria non inizializzata. Tiene traccia della «definitezza» e segnala il problema solo quando un valore indefinito ha effettivamente importanza, per esempio in un ramo, nell'output o in una chiamata di sistema.

In questo modo evita falsi allarmi quando si copiano byte non inizializzati senza conseguenze.

Uso dopo la liberazione

Accedere alla memoria dopo averla liberata è un comportamento indefinito. memcheck lo rileva con precisione.

Segnala una lettura non valida di dimensione 4 con la nota Address ... is 0 bytes inside a block of size 4 free'd e indica persino dove è stata eseguita la chiamata a free.

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

int main(void) {
    int *p = malloc(sizeof(int));
    *p = 7;
    free(p);
    printf("%d\n", *p);   /* read after free */
    return 0;
}

Doppia liberazione

Liberare lo stesso puntatore due volte corrompe la gestione interna dell'allocatore.

memcheck segnala Invalid free() e mostra sia la liberazione corrente sia l'allocazione originale, rendendo l'errore evidente.

#include <stdlib.h>

int main(void) {
    int *p = malloc(sizeof(int));
    free(p);
    free(p);   /* freed twice */
    return 0;
}

Tracciare le origini

Per gli errori dovuti a valori non inizializzati, aggiunga --track-origins=yes.

memcheck segnalerà quindi dove il valore errato è stato created, non solo dove è stato usato, trasformando un avviso generico in una correzione precisa.

valgrind --track-origins=yes ./prog

Stack e variabili globali

memcheck è particolarmente efficace per gli errori nell'heap. Per gli overflow nello stack o negli global arrays, la sua copertura è più limitata.

In questi casi, AddressSanitizer (gcc -fsanitize=address) è spesso la scelta migliore. I due strumenti si completano a vicenda.

Errore di una posizione: il terminatore nullo

Un overflow frequente nell'heap consiste nel dimenticare il terminatore della stringa. strlen restituisce 5 per 'hello', ma per memorizzare il '\0' finale la stringa richiede 6 byte.

memcheck segnala una scrittura non valida quando strcpy scrive l'ultimo byte oltre la fine.

#include <stdlib.h>
#include <string.h>

int main(void) {
    char *s = malloc(strlen("hello")); /* needs +1 */
    strcpy(s, "hello");                 /* writes the '\0' past end */
    free(s);
    return 0;
}

Verifica rapida

Identifichi ciò che memcheck segnala per il frammento di codice.

Riepilogo

Ora sa individuare i bug dovuti ad accessi non validi:

  • Le letture e scritture fuori dai limiti vengono segnalate come Invalid read/write con l'offset del blocco
  • I valori non inizializzati vengono segnalati quando influenzano una decisione o un output
  • Gli accessi dopo la liberazione e le doppie liberazioni vengono rilevati con entrambi i punti della chiamata
  • --track-origins=yes individua l'origine dei valori indefiniti; lo abbini ad ASan per i bug nello stack

Prossimo argomento: leggere il report completo.

Domande Frequenti

La lezione «Accessi non validi» è gratuita?

Sì — il testo completo di «Accessi non validi» è 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 «Accessi non validi»?

Accessi oltre i limiti e dati non inizializzati 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 3 di 4.

Quanto tempo richiede la lezione «Accessi non validi»?

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