0Pricing
C Academy · Lekcja

Wykrywanie wycieków

Podstawy memcheck

Wykrywanie wycieków to bezpłatna lekcja C Academy na CoddyKit. To lekcja 2 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

Wyciek pamięci występuje, gdy zaalokuje Pan / zaalokuje Pani pamięć sterty za pomocą malloc, calloc lub realloc, a następnie utraci wszystkie wskaźniki do niej przed wywołaniem free.

Blok pozostaje zarezerwowany, ale niedostępny aż do zakończenia procesu. W długo działających programach wycieki kumulują się, aż zabraknie pamięci.

Minimalny wyciek

Ten program powoduje wyciek jednego bloku o rozmiarze 40 bajtów.

Wskaźnik p jest zmienną lokalną. Gdy main zwróci sterowanie, p znika, ale wskazywany przez niego blok sterty nigdy nie zostaje zwolniony.

#include <stdlib.h>

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

Uruchamianie memcheck

memcheck jest narzędziem domyślnym, więc można pominąć nazwę narzędzia.

Dodaj --leak-check=full, aby uzyskać ślad stosu dla każdej wyciekającej alokacji.

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

Podsumowanie wycieków

Przy zakończeniu Valgrind wyświetla podsumowanie LEAK SUMMARY. Dla powyższego programu wygląda ono mniej więcej tak:

definitely lost: 40 bytes in 1 blocks

Ślad wskazuje dokładne miejsce wywołania malloc, dzięki czemu wiadomo, która alokacja nie została zwolniona.

Cztery kategorie wycieków

memcheck dzieli utraconą pamięć na cztery kategorie:

  • definitely lost — nie pozostał żaden wskaźnik; rzeczywisty wyciek
  • indirectly lost — dostępna wyłącznie przez blok oznaczony jako definitely lost
  • possibly lost — pozostał tylko wskaźnik wewnętrzny
  • still reachable — przy zakończeniu istnieje wskaźnik, ale pamięć nie została zwolniona

Definitely lost a still reachable

definitely lost to kategoria wymagająca pilnej uwagi: tych bajtów nie można odzyskać podczas działania programu.

still reachable jest łagodniejszą kategorią. Blok jest wyciekiem przy zakończeniu programu, ale nadal wskazuje na niego wskaźnik globalny lub statyczny, więc zwykle chodzi o jednorazową alokację, której po prostu nie zwolniono.

Wycieki pośrednie

Gdy utraci się początek połączonej struktury, każdy węzeł staje się niedostępny.

Początek jest oznaczany jako definitely lost, a pozostałe elementy jako indirectly lost. Usunięcie przyczyny źródłowej, czyli utraconego początku, odzyskuje całą pamięć.

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 */

Wersja poprawiona

Zwalniaj wszystko, co alokujesz. Ta wersja nie powoduje żadnych wycieków.

Uruchomiona pod kontrolą Valgrind zgłasza 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;
}

Zliczanie alokacji

Nawet przy braku wycieków podsumowanie HEAP SUMMARY informuje, jak intensywnie program korzystał z pamięci:

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

Gdy liczba alokacji i zwolnień się zgadza, uruchomienie przebiegło poprawnie. Niezgodność to pierwsza wskazówka, że coś nie zostało zwolnione.

Wyświetlanie dostępnych bloków

Domyślnie memcheck nie wyświetla szczegółowej listy bloków still reachable. Aby sprawdzić także je, dodaj:

--show-leak-kinds=all

Wymusza to ślad dla każdej kategorii i jest przydatne, gdy program ma zwalniać absolutnie wszystko przed zakończeniem.

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

Wycieki na ścieżkach błędów

Najbardziej podstępne wycieki kryją się na ścieżkach z wcześniejszym powrotem. W tym przypadku, jeśli druga alokacja się nie powiedzie, pierwszy blok wycieknie.

Zwykłe testy rzadko wykonują te gałęzie, ale memcheck wykrywa takie wycieki, gdy tylko dana ścieżka zostanie wykonana. Przed powrotem z obsługi błędu zawsze zwalniaj posiadaną pamięć.

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

Szybki test

Wybierz kategorię wycieku, która wymaga najpilniejszej uwagi.

Podsumowanie

Potrafi Pan już / Potrafi już Pani wykrywać wycieki za pomocą memcheck:

  • Uruchom valgrind --leak-check=full ./prog na pliku binarnym skompilowanym z opcją -g
  • Przeczytaj LEAK SUMMARY i HEAP SUMMARY
  • Najpierw zajmij się kategorią definitely lost, a następnie prześledź wycieki pośrednie do ich źródła
  • Użyj --show-leak-kinds=all, aby sprawdzić bloki still reachable

Następny temat: nieprawidłowy dostęp do pamięci.

Często zadawane pytania

Czy lekcja „Wykrywanie wycieków” jest bezpłatna?

Tak — pełny tekst „Wykrywanie wycieków” 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 „Wykrywanie wycieków”?

Podstawy memcheck Ć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 2 z 4.

Ile czasu zajmuje lekcja „Wykrywanie wycieków”?

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. Dlaczego Valgrind
  2. Wykrywanie wycieków
  3. Nieprawidłowy dostęp
  4. Odczytywanie raportów
← Powrót do C Academy