C Academy · Oppitunti

Vuotojen havaitseminen

memcheckin perusteet.

Oppitunti 2/413 vaihetta

Vuotojen havaitseminen on ilmainen C Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C Academy-kurssilla on yhteensä 4 oppituntia.

Mikä vuoto on

Muistivuoto syntyy, kun varaat kekomuistia funktiolla malloc, calloc tai realloc ja menetät kaikki siihen osoittavat osoittimet ennen free-funktion kutsumista.

Lohko pysyy varattuna mutta saavuttamattomana prosessin päättymiseen asti. Pitkään suoritettavissa ohjelmissa vuodot kasaantuvat, kunnes muisti loppuu.

Pienin mahdollinen vuoto

Tämä ohjelma vuotaa yhden 40 tavun lohkon.

Osoitin p on paikallinen muuttuja. Kun main palaa, p katoaa, mutta sen osoittamaa kekomuistilohkoa ei koskaan vapauteta.

#include <stdlib.h>

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

memcheckin suorittaminen

memcheck on oletustyökalu, joten työkalun nimen voi jättää pois.

Lisää --leak-check=full, niin saat pinon jäljityksen jokaisesta vuotaneesta varauksesta.

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

Vuotoyhteenveto

Valgrind tulostaa ohjelman päättyessä LEAK SUMMARY -yhteenvedon. Edellä mainitusta ohjelmasta se näyttää suunnilleen tältä:

definitely lost: 40 bytes in 1 blocks

Jäljitys osoittaa täsmälliseen malloc-kutsukohtaan, joten tiedät tarkalleen, mitä varausta ei vapautettu.

Neljä vuotokategoriaa

memcheck luokittelee kadonneen muistin neljään ryhmään:

  • definitely lost — yhtään osoitinta ei ole jäljellä; kyseessä on todellinen vuoto
  • indirectly lost — saavutettavissa vain definitely lost -lohkon kautta
  • possibly lost — jäljellä on vain osoitin lohkon sisälle
  • still reachable — osoitin on olemassa ohjelman päättyessä, mutta et koskaan vapauttanut lohkoa

Definitely lost ja still reachable

definitely lost on kiireellisin kategoria: näitä tavuja ei voi palauttaa ohjelman suorituksen aikana.

still reachable on lievempi tapaus. Lohko on vuotanut ohjelman päättyessä, mutta globaali tai staattinen osoitin viittaa siihen edelleen. Kyseessä on yleensä kertaluonteinen varaus, jota ei yksinkertaisesti ole muistettu vapauttaa.

Epäsuorat vuodot

Kun linkitetyn rakenteen alkuosoitin katoaa, jokaisesta solmusta tulee saavuttamaton.

Alkuosoitin näkyy luokassa definitely lost ja loput solmut luokassa indirectly lost. Kun korjaat perimmäisen syyn eli kadonneen alkuosoittimen, kaikki muisti saadaan palautettua.

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

Korjattu versio

Vapauta kaikki, minkä varaat. Tämä versio ei vuoda muistia.

Valgrind raportoi siitä 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;
}

Varausten laskeminen

HEAP SUMMARY -yhteenveto kertoo myös ilman vuotoja, kuinka paljon ohjelmasi käytti muistia:

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

Kun varausten ja vapautusten määrät täsmäävät, suoritus on puhdas. Ero määrissä on ensimmäinen vihje siitä, että jotain pääsi katoamaan.

Saavutettavissa olevien lohkojen näyttäminen

Oletuksena memcheck ei luettele still reachable -lohkoja yksityiskohtaisesti. Tarkasta myös ne lisäämällä:

--show-leak-kinds=all

Tämä pakottaa jäljityksen jokaiselle kategorialle. Se on hyödyllistä, kun haluat ohjelman vapauttavan kaiken muistin ennen päättymistä.

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

Virhepolkujen muistivuodot

Salakavalimmat vuodot piilevät ennenaikaisen paluun poluissa. Tässä tapauksessa ensimmäinen lohko vuotaa, jos toinen varaus epäonnistuu.

Tavallinen testaus osuu harvoin näihin haaroihin, mutta memcheck havaitsee vuodot aina, kun polku suoritetaan. Vapauta aina hallussasi oleva muisti ennen virheen yhteydessä palaamista.

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

Pikatesti

Valitse vuotokategoria, joka vaatii kiireellisintä huomiota.

Kertaus

Nyt osaat havaita muistivuodot memcheckillä:

  • Suorita valgrind --leak-check=full ./prog -g-valitsimella käännetylle binäärille
  • Lue LEAK SUMMARY- ja HEAP SUMMARY -yhteenvedot
  • Priorisoi definitely lost -tapaukset ja selvitä sitten epäsuorat vuodot niiden juurisyyhyn asti
  • Käytä --show-leak-kinds=all-valitsinta tarkastaaksesi edelleen saavutettavissa olevat lohkot

Seuraavaksi: virheelliset muistinkäytöt.

Aloita maksutta

Opi C tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
39
Oppitunnit
144

Usein kysytyt kysymykset

Onko oppitunti ”Vuotojen havaitseminen” ilmainen?

Kyllä – oppitunnin ”Vuotojen havaitseminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C Academy-kurssin, päivitä CoddyKit PROhon. C Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Vuotojen havaitseminen”?

memcheckin perusteet. Harjoittelet C Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni C Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin C Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Vuotojen havaitseminen”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä C Academy-oppitunnilla?

Kyllä. Jokainen C Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Miksi Valgrind
  2. Vuotojen havaitseminen
  3. Virheellinen käyttö
  4. Raporttien lukeminen
← Takaisin: C Academy