RUN - Ajaa sovelluksen ja näyttää miten muuttujat ja oliot luodaan pino- ja kekomuistiin ohjelman suorituksen aikana.
LOPETA - Demoaa sovelluksen päättymistä ja näyttää miten muisti vapautetaan. Pinomuisti vapautuu automaattisesti, mutta kekomuisti jää vuotamaan jos delete-operaattoria ei ole käytetty.
RAM (Random Access Memory) eli keskusmuisti on tietokoneen nopea, väliaikainen muisti, johon tallennetaan ohjelmien suorituksen aikana tarvittavaa dataa. RAM-muisti jaetaan eri alueisiin:
new-avainsanaanew) ja vapauttaa (delete) muistinew-operaattorillanew-operaattoria, muista aina vapauttaa muisti delete-operaattorillanullptr vapautuksen jälkeen välttääksesi roikkuvat osoittimetstd::unique_ptr, std::shared_ptr) jotka hoitavat muistinhallinnan automaattisesti
Muistivuoto syntyy kun new-operaattorilla varattu kekomuisti jätetään vapauttamatta delete-operaattorilla.
Ohjelma kuluttaa tällöin yhä enemmän muistia ajon aikana. Lyhyessä ohjelmassa tämä ei välttämättä näy,
mutta pitkään ajossa olevassa sovelluksessa, kuten palvelinohjelmistossa tai pelissä, muisti voi loppua kokonaan.
Dog* d = new Dog("Rex");
// delete d; <-- unohdettu, muisti pysyy varattuna ohjelman loppuun asti
Dangling pointer on osoitin joka viittaa jo vapautettuun muistialueeseen.
Muisti on vapautettu delete:llä, mutta osoitin osoittaa edelleen samaan paikkaan.
Olion käyttäminen tämän osoittimen kautta vapautuksen jälkeen aiheuttaa määrittelemätöntä toimintaa (undefined behavior). Ohjelma voi esimerkiksi kaatua.
Dog* d = new Dog("Rex");
delete d;
d->bark(); // vapautetun olion käyttäminen: määrittelemätön toiminta
Aseta osoitin nullptr:ksi vapautuksen jälkeen ja tarkista ennen käyttöä, ettei se ole tyhjä. Pelkkä nullptr:ksi asettaminen ei tee metodikutsusta turvallista: myös nullptr-osoittimen kautta kutsuminen aiheuttaa määrittelemätöntä toimintaa. Vaihtoehtoisesti käytä älykkäitä osoittimia (unique_ptr, shared_ptr), jotka hoitavat vapautuksen automaattisesti.
Dog* d = new Dog("Rex");
delete d;
d = nullptr; // d ei enää osoita vapautettuun muistiin
if (d != nullptr) {
d->bark(); // kutsu suoritetaan vain, jos d ei ole nullptr
} // tässä d on nullptr, joten kutsu ohitetaan
Huomautus: Osoitinta ei tarvitse tarkistaa ennen jokaista käyttöä, jos olion tiedetään olevan elossa. Tarkistus on hyödyllinen esimerkiksi silloin, kun ohjelman eri suorituspoluissa olio on saatettu jo vapauttaa. Tällöin osoitin pitää asettaa vapautuksen yhteydessä nullptr:ksi, jotta tarkistus toimii. Pelkkä nullptr-tarkistus ei tunnista roikkuvaa osoitinta. Jos olion elinaikaa on vaikea hallita, kannattaa suosia älykkäitä osoittimia.
Ajonaikaiset työkalut eivät lue lähdekoodia vaan tarkkailevat ohjelman toimintaa suorituksen aikana. Ne seuraavat muistin varauksia ja vapautuksia reaaliajassa ja raportoivat ohjelman lopussa mitä jäi vapauttamatta. Koska työkalu näkee vain ajetut koodipolut, ohjelma täytyy ajaa testiaineistolla joka kattaa kaikki haarat.
| Työkalu | Tekniikka | Alusta | Nopeus |
|---|---|---|---|
| Valgrind | Emuloi prosessoria ja näkee jokaisen muistiosoituksen. Merkitsee varatut alueet ja tarkistaa ohjelman lopussa onko niitä jäänyt vapauttamatta. | Linux | Hidas (10–50× hidastuma) |
| AddressSanitizer | Kääntäjä lisää ohjelmakoodiin automaattisesti tarkistusinstruktiota jokaisen muistioperaation ympärille. Aktivoidaan käännöslipulla -fsanitize=address,leak. |
Linux, macOS, Windows (GCC/Clang) | Nopea (~2× hidastuma) |
| Heob | Kytkeytyy ohjelmaan käynnistyksen yhteydessä ja korvaa Windowsin muistinhallinnan (HeapAlloc/HeapFree) omillaan, jolloin se voi seurata kaikkia varauksia. |
Windows | Keskinopea |
Staattisen analyysin työkalut lukevat lähdekoodin ilman että ohjelmaa ajetaan lainkaan. Ne etsivät koodista epäilyttäviä rakenteita ja tunnettuja virhekaavoja jo ennen käännöstä. Etuina ovat nopeus ja se, ettei testiaineistoa tarvita. Haittana on, että monimutkaisia ajonaikaisia tilanteita ei aina havaita.
| Työkalu | Kuvaus | Käyttö |
|---|---|---|
| Clang-Tidy | Clang-kääntäjän mukana tuleva analysaattori. Löytää mm. puuttuvia delete-kutsuja, dangling pointereita ja muita yleisiä virheitä. |
Integroituu suoraan CMakeen ja VS Codeen. Ilmainen. |
| Cppcheck | Pelkästään staattiseen analyysiin erikoistunut työkalu. Helppo asentaa ja ajaa, hyvä aloittelijoille. | Komentorivi tai IDE-lisäosa. Ilmainen. |
| Clang Static Analyzer | Syvällisempi kuin Clang-Tidy — seuraa koodin suorituspolkuja läpi funktioiden ja löytää monimutkaisempia vuotoja. | Ajetaan scan-build-komennolla. Ilmainen. |
| SonarCloud | Kattava pilvipalvelu joka raportoi muistivuotojen lisäksi koodin laadusta laajemmin. Integroituu GitHub Actionsiin. | Ilmainen julkisille repositoryille. |
Käytännössä staattinen analyysi ja ajonaikaiset työkalut täydentävät toisiaan: staattinen analyysi löytää virheet jo ennen ajamista, ajonaikaiset työkalut varmistavat että mitään ei jäänyt huomaamatta.