C Academy · Lektion

Ugyldig adgang

Adgang uden for grænser og ikke-initialiserede værdier

Lektion 3 af 413 trin

Ugyldig adgang er en gratis C Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i C Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. C Academy-kurset indeholder 4 lektioner i alt.

Ud over lækager

Lækager spilder hukommelse, men fejl med ugyldig adgang ødelægger den. memcheck fanger flere slags:

  • Læsning eller skrivning efter slutningen af en buffer
  • Brug af hukommelse efter free
  • Læsning af ikke-initialiserede værdier
  • Læsning eller skrivning gennem en ugyldig pointer

Det forårsager de farligste og sværest reproducerbare nedbrud.

Skrivning uden for grænserne

Dette allokerer plads til 5 int-værdier, men skriver til indeks 5, altså den sjette plads.

Indeks 5 ligger ét element efter slutningen. memcheck rapporterer en Invalid write of size 4 på denne linje.

#include <stdlib.h>

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

Læsning af fejlen

Rapporten angiver operationen, størrelsen og forholdet til blokken:

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

»0 bytes after a block of size 20« fortæller dig, at adgangen landede umiddelbart efter en allokering på 20 byte (5 int-værdier).

Læsning uden for grænserne

Læsninger bliver også fanget. Her kører løkken ét element for langt.

memcheck markerer en Invalid read of size 4 i den sidste iteration, selv om programmet måske fungerer »ved held«.

#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;
}

Ikke-initialiserede værdier

malloc nulstiller ikke hukommelsen. Hvis du bruger den, før du tildeler en værdi, får du en uforudsigelig værdi.

memcheck rapporterer Conditional jump or move depends on uninitialised value(s), når en sådan værdi påvirker kontrolflowet eller outputtet.

#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;
}

Hvorfor rapporter om ikke-initialiserede værdier kommer senere

memcheck klager ikke i det øjeblik, du læser ikke-initialiseret hukommelse. Det sporer, om værdier er »defined«, og rapporterer først, når en udefineret værdi faktisk betyder noget, f.eks. i en forgrening, i output eller i et systemkald.

Det undgår falske alarmer, når du uden problemer kopierer ikke-initialiserede byte rundt.

Brug efter frigivelse

Det er udefineret adfærd at tilgå hukommelse, efter at du har frigivet den. memcheck registrerer det præcist.

Det rapporterer Invalid read of size 4 med bemærkningen Address ... is 0 bytes inside a block of size 4 free'd og viser endda, hvor free blev udført.

#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;
}

Dobbelt frigivelse

Hvis du frigiver den samme pointer to gange, ødelægger du allokatorens bogføring.

memcheck rapporterer Invalid free() og viser både den aktuelle frigivelse og den oprindelige allokering, så fejlen bliver tydelig.

#include <stdlib.h>

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

Spor oprindelser

Ved fejl med værdier, der ikke er initialiseret, skal du tilføje --track-origins=yes.

memcheck rapporterer derefter, hvor den forkerte værdi blev created, ikke kun hvor den blev brugt, så en vag advarsel bliver til en præcis løsning.

valgrind --track-origins=yes ./prog

Stak og globale variabler

memcheck er fremragende til fejl i heapen. Ved overløb på stakken eller i globale arrays er dækningen svagere.

Her er AddressSanitizer (gcc -fsanitize=address) ofte det bedre valg. De to værktøjer supplerer hinanden.

Én for meget eller for lidt: Null-terminatoren

Et hyppigt heap-overløb skyldes, at strengterminatoren glemmes. strlen returnerer 5 for 'hello', men strengen kræver 6 bytes for at gemme den afsluttende '\0'.

memcheck rapporterer en ugyldig skrivning, når strcpy skriver den sidste byte efter slutningen.

#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;
}

Hurtigt tjek

Find ud af, hvad memcheck rapporterer for kodestykket.

Opsummering

Du kan nu identificere fejl med ugyldig adgang:

  • Læsninger og skrivninger uden for grænserne vises som ugyldig læsning/skrivning sammen med blokkens forskydning
  • Værdier, der ikke er initialiseret, markeres, når de påvirker en beslutning eller et output
  • Brug efter frigivelse og dobbelt frigivelse opdages med begge kaldesteder
  • --track-origins=yes lokaliserer udefinerede værdier; brug det sammen med ASan til fejl på stakken

Næste trin: læsning af hele rapporten.

Gratis at komme i gang

Lær C med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
39
Lektioner
144

Ofte stillede spørgsmål

Er lektionen “Ugyldig adgang” gratis?

Ja — hele teksten til “Ugyldig adgang” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af C Academy-kurset, skal du opgradere til CoddyKit PRO. C Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Ugyldig adgang”?

Adgang uden for grænser og ikke-initialiserede værdier Du øver dig i C Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på C Academy?

Der kræves ingen tidligere erfaring. C Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Ugyldig adgang”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne C Academy-lektion?

Ja. Alle C Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Hvorfor Valgrind
  2. Registrering af lækager
  3. Ugyldig adgang
  4. Læsning af rapporter
← Tilbage til C Academy