Joten, rupesin tänään ihan varmuuden vuoksi käyttämään Valgrindia että varmasti tietäisin jos muistia vuotaa. Työskentelen Linuxilla, ja myöskin C++:n yhteydessä käytän SDL:ää.
Satuinpa sitten tarkastamaan projektiani, ja sainkin valtavan liudan erroreita terminaaliin. Tässä esimerkki:
valgrind kirjoitti:
==25404== 8,192 bytes in 8 blocks are possibly lost in loss record 65 of 80
==25404== at 0x402703E: malloc (vg_replace_malloc.c:207)
==25404== by 0x406FA05: SDL_AllocFormat (SDL_pixels.c:133)
==25404== by 0x4071595: SDL_CreateRGBSurface (SDL_surface.c:102)
==25404== by 0x40ECEB9: TTF_RenderUNICODE_Solid (SDL_ttf.c:1105)
==25404== by 0x40ED28D: TTF_RenderText_Solid (SDL_ttf.c:1042)
==25404== by 0x8058855: Text(_TTF_Font*, SDL_Surface**, SDL_Color, std::string) (in /home/erakko/Työpöytä/cold_wave/main/main)
==25404== by 0x8071650: Medal::Medal(int, std::string, std::string, std::string, int, int, int) (in /home/erakko/Työpöytä/cold_wave/main/main)
==25404== by 0x8071A9C: MedalHandler::MedalHandler() (in /home/erakko/Työpöytä/cold_wave/main/main)
==25404== by 0x80BB6A3: main (in /home/erakko/Työpöytä/cold_wave/main/main)
Ja näitä löytyy sitten useampaan tilanteeseen muitakin, mutta se pisti silmään että en ainakaan omista koodeistani löytänyt vikaa, ja älysin että kaikki nuo rivit ovat yhteydessä toisiinsa, eli tämä on kuin backtrace tuloste GDB:llä. Eli jos näin on niin vika ei siis ole välttämättä minun, vaan Valgrindin tai jopa SDL:n.
Ajoin siis valgrindin näin:
terminaali kirjoitti:
valgrind --leak-check=yes --track-origins=yes ./main
Main on siis tämä ohjelma.
Erroreita kuitenkin löytyy paljon, ja kun kaikki ovat vielä peräisin noinkin juuresta niin mietin onko tämä loppupeleissä luotettava ohjelma, tai sitten ollenkaan vakavasti otettava errori.
Toisaalta, näitä lukuja on hyvin vaikea olla ottamatta vakavasti:
valgrind kirjoitti:
==25404== LEAK SUMMARY:
==25404== definitely lost: 22,262 bytes in 388 blocks.
==25404== indirectly lost: 287,408 bytes in 1,574 blocks.
==25404== possibly lost: 891,376 bytes in 24 blocks.
==25404== still reachable: 153,864 bytes in 1,046 blocks.
==25404== suppressed: 0 bytes in 0 blocks.
Voin myös näyttää koko Valgrind ilmoituksen jos tunnette tarpeelliseksi.
Nuo eivät ole erroreita, ne ovat vain ilmoituksia vuotavasta muistista. Nuo funktiolistat ovat backtracea siitä että mitä kautta vuodon aiheuttavaa kohtaa kutsutaan. Tuossa esimerkissä muisti vuotaa tässä:
by 0x406FA05: SDL_AllocFormat (SDL_pixels.c:133)
Varaat muistia mallocilla, mutta et ilmeisesti vapauta sitä.
valgrind kirjoitti:
==6583== 10 bytes in 2 blocks are definitely lost in loss record 7 of 75
==6583== at 0x402703E: malloc (vg_replace_malloc.c:207)
==6583== by 0x4909D72: (within /usr/lib/libX11.so.6.2.0)
==6583== by 0x4908D11: _XimEncodeLocalICAttr (in /usr/lib/libX11.so.6.2.0)
==6583== by 0x490A058: _XimSetICValueData (in /usr/lib/libX11.so.6.2.0)
==6583== by 0x4902B7E: _XimLocalCreateIC (in /usr/lib/libX11.so.6.2.0)
==6583== by 0x48E5DF8: XCreateIC (in /usr/lib/libX11.so.6.2.0)
==6583== by 0x4085AA9: create_aux_windows (SDL_x11video.c:515)
==6583== by 0x4086C8A: X11_VideoInit (SDL_x11video.c:682)
==6583== by 0x40749F3: SDL_VideoInit (SDL_video.c:240)
==6583== by 0x4047952: SDL_InitSubSystem (SDL.c:70)
==6583== by 0x40479B6: SDL_Init (SDL.c:162)
==6583== by 0x80C66EB: main (in /home/erakko/Työpöytä/cold_wave/main/main)
==6583==
==6583==
==6583== 12 bytes in 1 blocks are definitely lost in loss record 11 of 75
==6583== at 0x402703E: malloc (vg_replace_malloc.c:207)
==6583== by 0x49BCCFD: ???
==6583== by 0x49BC6ED: ???
==6583== by 0x49BC804: ???
==6583== by 0x49BCF9E: ???
==6583== by 0x49B7D0D: ???
==6583== by 0x49B811D: ???
==6583== by 0x407C3DD: XShmQueryExtension (SDL_x11sym.h:160)
==6583== by 0x4086D79: X11_VideoInit (SDL_x11video.c:623)
==6583== by 0x40749F3: SDL_VideoInit (SDL_video.c:240)
==6583== by 0x4047952: SDL_InitSubSystem (SDL.c:70)
==6583== by 0x40479B6: SDL_Init (SDL.c:162)
==6583==
==6583==
==6583== 224 (16 direct, 208 indirect) bytes in 2 blocks are definitely lost in loss record 23 of 75
==6583== at 0x402715C: realloc (vg_replace_malloc.c:429)
==6583== by 0x48EBF04: (within /usr/lib/libX11.so.6.2.0)
==6583== by 0x48ECBD8: (within /usr/lib/libX11.so.6.2.0)
==6583== by 0x48EE4CF: (within /usr/lib/libX11.so.6.2.0)
==6583== by 0x48EEC57: _XlcCreateLC (in /usr/lib/libX11.so.6.2.0)
==6583== by 0x490E15A: _XlcDefaultLoader (in /usr/lib/libX11.so.6.2.0)
==6583== by 0x48F5A91: _XOpenLC (in /usr/lib/libX11.so.6.2.0)
==6583== by 0x48F5BD2: _XlcCurrentLC (in /usr/lib/libX11.so.6.2.0)
==6583== by 0x48F6080: XSetLocaleModifiers (in /usr/lib/libX11.so.6.2.0)
==6583== by 0x407C21D: XSetLocaleModifiers (SDL_x11sym.h:149)
==6583== by 0x4085C57: create_aux_windows (SDL_x11video.c:468)
==6583== by 0x4086C8A: X11_VideoInit (SDL_x11video.c:682)
Nämä ovat mietityttäneet nyt jo jonkin aikaa, ovat aika pieniä, mutta eivät näytä olevan itse aiheutettuja. Ensimmäinen voi olla mutta ainakaan viimeinen ei ole minulle millään tapaa tuttu - paitsi kun sen on nyt lukenut monta kertaa tuosta.
Loput ovatkin sitten itse aiheutettuja. Tulee olemaan ilmeisesti aika kova homma niiden kaikkien korjaamisessa. Huoh, varmaan pitäisi opiskella enemmän teoriaa että osaisi välttyä tälläiseltä jälkipyykiltä...
Eikö noi SDL_Initin varaukset saa vapautettua SDL_Quit:lla, eli puuttuuko SDL_Quit?
Ainakin itselläni SDL vuotaa muistia aina jonkin verran. Tämän ei pitäisi olla vakavaa, koska vuoto on suhteellisen pieni ja koskee vain alustusvaiheessa tehtyjä varauksia. Siten vuodetun muistin määrä ei kasva rajatta suorituksen aikana, ellei ole muita vuotoja.
Noistakin voisi vielä huomata, että varsinainen vuotaja ei aina ole SDL vaan joissain tapauksissa X, jota SDL käyttää Linuxilla grafiikka-asioissa. Osa varauksista saattaa olla myös sellaisia, että niitä tunnetusti tarvitaan käytännössä ohjelman alusta loppuun asti, jolloin ei ole pidetty tarpeellisena säilyttää niiden osoittimia.
Lisäksi kannattaa muistaa, ettei valgrind mitenkään voi pysyä mukana kaiken koodin toiminnassa. Tässäkin ohjelmassa on valgrindin mukaan ehdottomasti hukkunut neljä tavua. Kommentin sisällä on asianmukainen free, jolla varatun muistin saisi silti vapautettua. (Erikoisesti valgrindin lopputulos on erilainen, jos +4 lisätäänkin vasta seuraavalla rivillä.)
#include <stdlib.h> int main() { char *i = malloc(4) + 4; /* free(i - 4); */ }
Omat lukusi taas ovat kieltämättä sellaisia, että kannattaa tarkkaan tarkistaa, että oma koodisi vapauttaa kaikki SDL-pinnat, fontit jne.
Grez kirjoitti:
Eikö noi SDL_Initin varaukset saa vapautettua SDL_Quit:lla, eli puuttuuko SDL_Quit?
Ei puutu.
Nojaa, ei se niin kova homma ollutkaan. Luulin että "still reachable" kohteet olisivat vielä itseaiheutettuja, mutta nekin menevät samaan kastiin noiden kolmen kanssa mitkä näytin. Jollei näillekään nyt tarvitse tehdä mitään niin sitten voin olla tyytyväinen ja kiitän tiedoista.
Loppupeleissä Leak Summary jäi tälläiseksi:
valgrind kirjoitti:
==6242== LEAK SUMMARY:
==6242== definitely lost: 38 bytes in 5 blocks.
==6242== indirectly lost: 208 bytes in 8 blocks.
==6242== possibly lost: 0 bytes in 0 blocks.
==6242== still reachable: 78,044 bytes in 959 blocks.
==6242== suppressed: 0 bytes in 0 blocks.
Aihe on jo aika vanha, joten et voi enää vastata siihen.