0Pricing
C Academy · Lekcja

Wycieki pamięci

Wykrywanie i unikanie wycieków

Wycieki pamięci to bezpłatna lekcja C Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C Academy zawiera 4 lekcji w sumie.

Czym jest wyciek pamięci

Wyciek pamięci występuje, gdy zaalokujesz pamięć na stercie, ale nigdy jej nie zwolnisz i utracisz jedyny wskaźnik do niej.

Pamięć pozostaje zarezerwowana aż do zakończenia programu, powodując marnowanie zasobów.

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

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

Utrata wskaźnika

Klasyczny wyciek polega na nadpisaniu wskaźnika nową alokacją przed zwolnieniem starej.

Pierwszy blok staje się nieosiągalny.

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

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

Wycieki w pętlach

Alokowanie pamięci wewnątrz pętli bez zwalniania jej w każdej iteracji szybko zwielokrotnia wyciek.

Rozwiązaniem jest zwolnienie pamięci przed kolejną iteracją, która nadpisze wskaźnik.

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

int main(void) {
    for (int i = 0; i < 3; i++) {
        int *p = malloc(sizeof(int));
        *p = i;
        printf("%d ", *p);
        free(p);
    }
    printf("\n");
    return 0;
}

Wczesne return powoduje wyciek

Wczesne return po alokacji może pominąć sprzątanie. Zawsze zwalniaj pamięć na każdej ścieżce wyjścia.

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

int process(int bad) {
    int *p = malloc(sizeof(int));
    if (bad) {
        free(p);
        return -1;
    }
    *p = 42;
    int r = *p;
    free(p);
    return r;
}

int main(void) {
    printf("%d\n", process(0));
    return 0;
}

Schemat sprzątania z goto

Pojedyncza etykieta sprzątania, do której prowadzi goto, zapewnia jedno miejsce zwalniające całą pamięć i pozwala uniknąć powielania wywołań free.

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

int main(void) {
    int rc = 1;
    int *p = malloc(sizeof(int));
    if (!p) goto done;
    *p = 7;
    printf("%d\n", *p);
    rc = 0;
done:
    free(p);
    return rc;
}

Dopasuj zwolnienie do każdej alokacji

Najprostsza zasada: każdemu wywołaniu malloc, calloc lub realloc musi odpowiadać dokładnie jedno wywołanie free.

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

int main(void) {
    char *a = malloc(8);
    char *b = calloc(4, sizeof(char));
    a[0] = 'x';
    printf("%c %d\n", a[0], b[0]);
    free(a);
    free(b);
    return 0;
}

Zwalnianie zagnieżdżonych alokacji

Jeśli struktura zarządza pamięcią na stercie, zwolnij wewnętrzne wskaźniki przed zwolnieniem zewnętrznego bloku.

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

typedef struct {
    int *data;
} Box;

int main(void) {
    Box *b = malloc(sizeof(Box));
    b->data = malloc(3 * sizeof(int));
    b->data[0] = 1;
    printf("%d\n", b->data[0]);
    free(b->data);
    free(b);
    return 0;
}

Zwalnianie tablicy wskaźników

Gdy alokujesz tablicę wskaźników, a każdy element jest osobną alokacją, najpierw zwolnij każdy element, a dopiero potem tablicę.

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

int main(void) {
    int n = 3;
    int **rows = malloc(n * sizeof(int *));
    for (int i = 0; i < n; i++) {
        rows[i] = malloc(2 * sizeof(int));
        rows[i][0] = i;
    }
    for (int i = 0; i < n; i++) free(rows[i]);
    free(rows);
    printf("freed all rows\n");
    return 0;
}

Zasady własności

Ustal, kto posiada każdą alokację i odpowiada za jej zwolnienie. Udokumentuj to, aby osoby wywołujące funkcję wiedziały, czy muszą zwolnić zwrócony wskaźnik.

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

char *make_greeting(void) {
    char *s = malloc(6);
    s[0]='h'; s[1]='i'; s[2]='\0';
    return s;
}

int main(void) {
    char *g = make_greeting();
    printf("%s\n", g);
    free(g);
    return 0;
}

Narzędzia wykrywające wycieki

Narzędzia takie jak Valgrind i AddressSanitizer wykrywają wycieki, śledząc każdą alokację i wskazując te, które nigdy nie zostały zwolnione.

Są niezbędne do weryfikowania rzeczywistych programów.

Cykl życia poprawnej alokacji

Podsumowując: alokuj pamięć, sprawdzaj wynik, używaj jej, zwalniaj na każdej ścieżce i wyzeruj wskaźnik. Dzięki temu programy pozostają wolne od wycieków.

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

int main(void) {
    int *p = malloc(4 * sizeof(int));
    if (!p) return 1;
    for (int i = 0; i < 4; i++) p[i] = i + 1;
    int sum = 0;
    for (int i = 0; i < 4; i++) sum += p[i];
    printf("sum = %d\n", sum);
    free(p);
    p = NULL;
    return 0;
}

Szybkie sprawdzenie

Sprawdź swoje zrozumienie wycieków pamięci.

Podsumowanie

Dowiedziałeś się, jak zapobiegać wyciekom pamięci:

  • Każdą alokację dopasuj do dokładnie jednego wywołania free.
  • Zwalniaj pamięć na każdej ścieżce wyjścia, także przy wczesnych zwrotach i błędach.
  • Zwalniaj zagnieżdżone alokacje oraz alokacje tablic wskaźników, zaczynając od elementów wewnętrznych.
  • Jasno określaj własność pamięci i używaj narzędzi takich jak Valgrind do weryfikacji.

Często zadawane pytania

Czy lekcja „Wycieki pamięci” jest bezpłatna?

Tak — pełny tekst „Wycieki pamięci” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C Academy, przejdź na CoddyKit PRO. Kurs C Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wycieki pamięci”?

Wykrywanie i unikanie wycieków Ćwiczysz C Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C Academy?

Nie wymagamy żadnego doświadczenia. C Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Wycieki pamięci”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C Academy?

Tak. Każda lekcja C Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. malloc i free
  2. calloc i realloc
  3. Wycieki pamięci
  4. Wiszące wskaźniki
← Powrót do C Academy