räknas lokala variabler med i minnesåtgången?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

räknas lokala variabler med i minnesåtgången?

Inlägg av jesse »

Hur vet jag om jag gör åt för mycket RAM-minne eller inte? :humm:

Håller på med ett AVR-program nu (I AVRStudio5 som använder sig av GCC). och får följande meddelande när jag kompilerar:
AVR Memory Usage
----------------
Device: atmega644
Program: 30910 bytes (47.2% Full)
(.text + .data + .bootloader)
Data: 2177 bytes (53.1% Full)
(.data + .bss + .noinit)
EEPROM: 277 bytes (13.5% Full)
(.eeprom)
om jag förstår saken rätt så lagras de globala variablerna i fasta minnesadresser, men lokala variabler uppstår och försvinner när funktioner anropas. Jag undrar om det gäller även lokala arrayer (t.ex. en sträng)... Dessa kan ju ta hur mycket utrymme som helst, och man kan ju hamna låååångt över tillåten gräns om man inte ser upp.

Hamnar alla lokala variabler på stacken?

Det är väl i så fall knappast möjligt för kompilatorn att räkna ut hur mycket minne som eventuellt kan gå åt då?
Finns det något sätt för mig att veta att jag inte går för långt i minnesanvändningen?

Behöver jag förstöra data i vissa fall för att frigöra minne?

vad betyder .data .bss och .noinit ???
-----------------------------------------------------------------------------------------
EDIT: läste lite här...

Och som jag misstänkte så är det bara de globala variablerna som finns med i "Data".
Tänk om jag lägger alla stora arrayer i main() istället för globalt - då kommer dessa alltså inte att synas!
Och jag tror att jag har massor av utrymme kvar! Hur sjutton kan man vara säker på det?

Måste jag räkna ut för hand hur mycket plats alla lokala variabler kommer att ta, eller finns det något sätt att få reda på det? (Fast optimeringen gör ju också att en variabel kanske hinner försvinna innan nästa skapas vilket då sparar minne... så det blir kanske ändå en gissning. Men man kan väl i alla fall räkna ut hur mycket SRAM en funktion kan utnyttja maximalt?

Så länge man inte programmerar rekursivt kan man då gå igenom alla nivåer (det blir ju ett herrans jobb!).
Användarvisningsbild
AndLi
Inlägg: 18288
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av AndLi »

Du målar stacken med ett känt värde, sen kör du din kod ett tag och ser till att så mycket som möjligt av koden körs. Sen kollar du hur mycket av stacken som fortfarande har ditt ditmålade värde.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av jesse »

ah, yeah... Tack för tipset. Det kan fungera... :tumupp:

Då gäller det att verkligen försöka använda alla funktioner fullt ut och fylla alla skrymslen med data så det inte står oanvänt.... för annars syns det ju inte.... ska testa... får bli minnesdump via RS232...
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46989
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av TomasL »

Huruvida lokala variabler räknas, beror på kompilatorn, olika kompilatorer har olika algoritmer för optimering och visar info på olika sätt..
Lokala variabler bör rimligtvis hamna i en "scratch-pad" /stack eller liknande, dock helt beroende på optimeringar osv.
Nerre
Inlägg: 27235
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av Nerre »

Ja hålla koll på stacken manuellt går ju inte, har man t.ex. rekursiva funktioner så kan den ju sticka iväg rejält. Men blir stacken full får man väl ett "stack overflow" felmeddelande (som man bör ta hand om)? Eller måste processorn stödja det? (D.v.s. det är inget som C har inbyggt?)
thebolt
Inlägg: 248
Blev medlem: 10 februari 2008, 17:41:40
Ort: Taipei Taiwan

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av thebolt »

jesse skrev: om jag förstår saken rätt så lagras de globala variablerna i fasta minnesadresser, men lokala variabler uppstår och försvinner när funktioner anropas. Jag undrar om det gäller även lokala arrayer (t.ex. en sträng)... Dessa kan ju ta hur mycket utrymme som helst, och man kan ju hamna låååångt över tillåten gräns om man inte ser upp.
Lokala arrayer beror lite på hur de definieras (förutsätter gcc nu), en static const array hamnar troligen i .data eller .text på de flesta akritekturer, jag skulle gissa att på AVR blir det .data då flashen (och därmed .text) kräver speciella instruktioner för att läsas.
jesse skrev: Hamnar alla lokala variabler på stacken?
Det är väl i så fall knappast möjligt för kompilatorn att räkna ut hur mycket minne som eventuellt kan gå åt då?
På stacken eller i register, om det är en liten funktion med ett fåtal variabler. Och du har helt rätt i att det är väldigt svårt att med sk statisk analys (utan att köra programmet) bestämma minnesanvändning. Har du inga rekursiva funktioner eller enbart tail-recursion går det, i annat fall är det näst intil omöjligt. Jag är ganska säker på att gcc inte gör detta, och avr-size-programmet kan defintivt inte göra det.
jesse skrev: Måste jag räkna ut för hand hur mycket plats alla lokala variabler kommer att ta, eller finns det något sätt att få reda på det? (Fast optimeringen gör ju också att en variabel kanske hinner försvinna innan nästa skapas vilket då sparar minne... så det blir kanske ändå en gissning. Men man kan väl i alla fall räkna ut hur mycket SRAM en funktion kan utnyttja maximalt?

Så länge man inte programmerar rekursivt kan man då gå igenom alla nivåer (det blir ju ett herrans jobb!).
Precis, du kan alltid hitta en övre gräns på hur mycket en funktion tar.. tittar du på den genererade assembly-koden kan du också läsa av hur mycket stack-utrymme varje funktion reserverar i de inledande instruktionerna.

Rent generellt.. vid programmering på platformar med lite minne gäller det att hålla reda på vad man använder minne för själv, det är inget någon annan kommer göra åt dig ;)
Nerre skrev: Ja hålla koll på stacken manuellt går ju inte, har man t.ex. rekursiva funktioner så kan den ju sticka iväg rejält. Men blir stacken full får man väl ett "stack overflow" felmeddelande (som man bör ta hand om)? Eller måste processorn stödja det? (D.v.s. det är inget som C har inbyggt?)
Går och går, det är mycket jobb. Har du rekursiva funktioner får du räkna på hur mycket varje djup i kedjan tar, och sen multiplicera detta med maximalt rekursionsdjup. Och nej, du får inget meddelande om du använder för mycket stack. C i sig har inget koncept om begränsat minne, det antas att du har oändligt med stack-utrymme. Så vitt jag har sett finns det ingen som hanterar detektering av "stack overflow" utan att använda sig av minnesskydd (t.ex. i samband med virtuellt/pageat minne).

För att citera min lärare i en DSP-konstruktionskurs "Ett vanligt problem är att staken växer okontrollerat" ;)
thepirateboy
EF Sponsor
Inlägg: 2109
Blev medlem: 27 augusti 2005, 20:57:58
Ort: Borlänge

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av thepirateboy »

jesse skrev: Och som jag misstänkte så är det bara de globala variablerna som finns med i "Data".
Tänk om jag lägger alla stora arrayer i main() istället för globalt - då kommer dessa alltså inte att synas!
Och jag tror att jag har massor av utrymme kvar! Hur sjutton kan man vara säker på det?

Att deklarera stora arrayer i funktioner inkl. main är för mig big no no. Har gjort misstaget några gånger tills
systemet crashat och det är då man förstår att avr-size-programmet bara räknar på globala variabler.

Dela istället upp programmet i filer och deklarera stora variabler högst upp i dessa filer så kommer dom dom
med i beräkningar. Deklarera dom gärna static också. På så sätt kapslar du in variablerna samtidigt som du
undviker stack problem. Se samtidigt till att du alltid har minst 100 bytes ledigt RAM för stacken.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av jesse »

Tack för alla svar.

Och jag som lärt mig att man ska undvika globala variabler om det inte är absolut nödvändigt. Där fick jag mig en läxa!
Inget har kraschat hittills, men så länge jag utvecklar vidare så är det väl bara en tidsfråga.

Nu funderar jag på att fylla RAM-minnet med 0x55 eller liknande, för att sedan (efter att ha kört ett bra tag) dumpa minnet.
Frågan: hur fyller jag detta bäst utan att spåra ur? Skulle egentligen kunna lägga in det sist i bootloadern och sedan göra ett jump till 0x0000, men slipper helst ändra i den.

Eller så gör jag ett RAM-dump i början av programmet (och hoppas att efter ett power-down-reset så får RAM-minnet att innehålla ett ganska enformigt innehåll...) och sedan i slutet av programmet en gång till, för att sedan jämföra data.

Jag kör inte rekursivt, annat än i ett par mycket små funktioner som bara går ner max 2 nivåer.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46989
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av TomasL »

Det finns ju globala variabler för hela projektet och globala för kod-modulen (dvs din C-Fil)
Det är väl projektglobala variabler man vill undvika.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av jesse »

Det beror väl på hur många funktioner man vill samla i samma fil, men principiellt har du rätt, ja.
Det aktuella projektet har just nu sju .c-filer (och sju .h-filer), varav main.c är den i särklass största.
Det hade säkert gått att bryta ut vissa funktioner och lägga i egna filer, men då blir det fler projekt-globala variabler.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av jesse »

Försöker analysera minnesåtgången, och jag får säga att jag är imponerad av GCC's optimering!
De allra flesta call använder 3 eller 4 bytes på stacken! Det är returadressen (2 bytes) plus 1 eller 2 bytes push-pop. Har hittills inte sett en enda lokal variabel i SRAM! De verkar ligga i register. (Jag testar med simulatorn i AVRstudio)

(Undantag är givetvis interrupt som måste spara undan en hel del)

Jag har faktiskt inte (vad jag kan se) några lokala arrayer.

Frågan uppstod egentligen nu eftersom jag håller på att skriva några funktioner som bearbetar text. Antingen har varje funktion sin egen lokala textbuffert, eller så deler de på samma globala "slaskbuffert".

Här kommer då dilemmat:

1) om jag kör globalt, kommer den alltid att ta upp minne, även när den inte behövs. Då blir det mindre minne över till resten av programmet.
2) om jag kör lokalt så tar den upp minne tillfälligt och försvinner sedan. Men då kan jag inte se lika lätt hur mycket marginal jag har...

EDIT: när jag kör lite större funktioner (som i sin tur anropar en massa andra och så kör interrupten dessutom under tiden) så har jag kommit upp i 32 byte som mest. Men jag irriterar mig lite på att stackpekaren ligger på 10EB när main() startar --- vad är det för skit den lagrar i stacken innan? Det kommer väl aldrig att användas då jag aldrig gör retur från main(). SKulle man kunna justera stacken i början och sätta den till 1100 där den borde börja? (Ja AVR är konstig; SRAM börjar på 0x100 och slutar på 0x1100 om jag har 4096 bytes :doh: )
monstrum
Inlägg: 620
Blev medlem: 13 januari 2005, 05:38:32
Ort: Göteborg

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av monstrum »

Om det handlar om ickestatiskt minne som behövs som temporär lagring så är det ju inget fel att lägga detta på stacken. Man får som sagt bara ha koll så att man inte får slut på stack. Kör man bara med statiskt allokerade globala variabler så funkar dels inte rekursion, och dels kommer man antagligen behöva mer minne totalt.
Användarvisningsbild
Icecap
Inlägg: 26652
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av Icecap »

Att "fast" deklarerade minnesbuffrar ska vara "bortkastade" när de inte används är knappast korrekt, jag brukar att använda en union om jag är säker på att de inte kommer att användas samtidig, då kan ett och samma minnesarea användas till ganska många funktioner.

Är det "småpotatis" som jag behöver lokalt har jag inget problem med att deklarera dom lokalt men alla kännbara storlekar låter jag vara globala (och mycket gärna union's) eller statiska.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av jesse »

Såg att jag hade 512 bytes skrivbuffert till UART. Kanske lite overkill. Borde klara mig med 64 bytes... :roll:

Angående vad någon frågade om tidigare: Jag kan inte tänka mig att en AVR varnar för stack-overflow! Den kör bara vidare och skriver över allt som finns.
monstrum
Inlägg: 620
Blev medlem: 13 januari 2005, 05:38:32
Ort: Göteborg

Re: räknas lokala variabler med i minnesåtgången?

Inlägg av monstrum »

Icecap skrev:Att "fast" deklarerade minnesbuffrar ska vara "bortkastade" när de inte används är knappast korrekt, jag brukar att använda en union om jag är säker på att de inte kommer att användas samtidig, då kan ett och samma minnesarea användas till ganska många funktioner.

Är det "småpotatis" som jag behöver lokalt har jag inget problem med att deklarera dom lokalt men alla kännbara storlekar låter jag vara globala (och mycket gärna union's) eller statiska.
Ja, unions (unioner?) är ju självklart ett fiffigt sätt. Man måste ju dock ha stenkoll på vad man sysslar med då, vilket man förvisso alltid skall ha oavsett.
Skriv svar