AVR atminties nutekėjimas: TOP#1

Posted: 2013-10-03 in Darbeliai
Žymos:, ,

Na, kokiame rimtame projekte nebūna atminties nutekėjimų (memory leak)? Čia visų programuotojų galvos skausmas, nebent jie programuoja tai, ko niekam nereikia 😀

TQFP tipo mikroschema | Darau, blėSu mikrovaldikliais, aišku, tokis reikalas ypač skausmingas, nes ten tos atminties nėra labai daug. Tiesa, rūpestingai dėliojant kodą ta problema nelabai dažna, bet, žinote, užsiroviau. Ir likau labai nustebęs. Atmintis pradėjo nykti akyse ir valdiklis užstrigo.

Tai va, nežinau, kas kaltas: ar pats mikrovaldiklis, ar GCC kompiliatorius. Bet paprasta ir, atrodo, nelabai rimta klaida gali suėsti visą jo atmintį. Klaida paprasta: neteisingai parinktas kintamojo tipas. Aš stengiuosi resursų be reikalo nešvaistyti ir naudoti uint8_t duomenų tipą visokiems kintamiesiems, kuriems užtenka reikšmės nuo 0 iki 255. T.y. vieno baito.

Taip padariau ir vakar vakare: įvedžiau tokį kintamąjį. Iš įpratimo. O sąlygą parašiau paprastą: if (x > 512)… Suprantate, juokinga klaida. Kintamojo reikšmė iki 255, o aš lyginau su didesne, nei įmanoma. Na, šiaip, normaliai, būtų galima tikėtis, kad ta sąlyga tiesiog niekad neįvyks ir tiek. O va AVR procesoriuje vieno baito kintamojo palyginimas su dviejų baitų skaičiuku baigėsi atminties surijimu. Pakeitus uint8_t į uint16_t viskas iš karto susitvarkė.

Kokia to priežastis — nežinau. Ale dalinuosi ir perspėju.

Advertisements
Komentarai
  1. Vytautas Šaltenis parašė:

    Labai keista. O kas buvo po if’u?.. Ir kodėl gcc warningais neaplojo? 🙂

    • Darau, Blė parašė:

      Labai paprastas tokis makrosiukas:

      #define SERVO_UPDATE_COUNTER() \
      	if (timer0_cnt++ == 1250) { \
      		timer0_cnt = 0; \
      	}
      

      O warningų gi tikri vyrai neskaito, ane? Tik errorus!

      • n/a parašė:

        siaip blogis yra tikrinti reiksmes virsijima su lygybe (skaitliuka gali kas nors kitas padidinti, o tada jau lauk bedos), todel siuo atveju geriau butu naudoti:

        #define SERVO_UPDATE_COUNTER() \
        if (timer0_cnt++ >= 1250) { \
        timer0_cnt = 0; \
        }

        nebent cia tikrai norima nuresetint butent tik kai reiksme lygi 1250

        • Darau, Blė parašė:

          Taip, pastabėlė teisinga, visada geriau „>=“ arba „<=“. Na, o praktiškai tai yra kode vienintelė vieta, kur skaitliuko reikšmė keičiama, taip kad nėra baisiai svarbu.

  2. Vytautas Šaltenis parašė:

    Joo, plika akimi tikrai nieko nesimato, kažkoks subtilus ripple effect ar kas nors tokio. Jeigu išsiaiškinsi, parašyk, nepalik cliffhangerio 🙂

    O kas liečia warningus, tai jo, tikri vyrai įsijungia -Werror ir tada tai jau tikrai warningų neskaito, tik errorus 😀

Parašykite komentarą

Įveskite savo duomenis žemiau arba prisijunkite per socialinį tinklą:

WordPress.com Logo

Jūs komentuojate naudodamiesi savo WordPress.com paskyra. Atsijungti / Keisti )

Twitter picture

Jūs komentuojate naudodamiesi savo Twitter paskyra. Atsijungti / Keisti )

Facebook photo

Jūs komentuojate naudodamiesi savo Facebook paskyra. Atsijungti / Keisti )

Google+ photo

Jūs komentuojate naudodamiesi savo Google+ paskyra. Atsijungti / Keisti )

Connecting to %s