Fråga:
Varför returnerar min atmega32s malloc-funktion pekaren i flera av fyra?
MaNyYaCk
2016-12-03 23:55:10 UTC
view on stackexchange narkive permalink

Jag är i en inlärningsfas så jag är ingen proffs när det gäller att förstå minnet och därmed har jag lite problem med att förstå några saker

  1. Databladet för atmega32 säger att det kommer med 2K SRAM Page 17 of Datasheet explaining SRAM

Hur blir det 2k?

  1. När jag körde följande kod i en oändlig slinga tills den returnerar 0, returnerade malloc-funktionen mig med adresser i multiplar av 4 för Atmega32.

      p = (char *) malloc (sizeof (char));
     

    Enligt vad jag förstår är karaktären av 1 byte, därför borde den ge mig intilliggande adresser istället?

0060 till 085F är 2K.Om varför malloc insisterar på ordjustering måste du läsa avr-libc-dokumentationen eller källkoden.(Att frigöra och omfördela enstaka byte skulle lämna hopplös fragmentering, så det är den troliga anledningen).Men att använda malloc är inte mycket meningsfullt med bara 2K-minne.
EDIT: Bara min gissning.Arkitekturen följer lilla Endian så att värdet börjar lagras från högre till lägre adress.Eftersom det är en 8-bitars styrenhet lagras data i en adress som är multipel av 8.
Det är inte ovanligt att C-bibliotek fördelar i multiplar om 4 eller till och med större.Speciellt på ett 32-bitars system.
Var försiktig med terminologi - ATMEGA32 vet ingenting om malloc eller dynamisk minneshantering, detta är enbart en kompilatorfunktion.Andra kompilatorer än gcc kan fungera annorlunda.
@KevinWhite noteras.Men jag arkitektur gör skillnad?
@BrianDrummond Vad betyder det sista uttalandet?
Att använda malloc på en mikrokontroller är nästan meningslöst.
@whatsisname Varför är det så?
Eftersom http://electronics.stackexchange.com/questions/146298/what-happens-when-microcontrollers-run-out-of-ram/146364#146364
I grund och botten: för att standarden säger det
Noteras.Men jag arkitektur gör skillnad?- MaNyYaCk.@MaNyYaCk - Ja men AVR-arkitekturen tillåter 8bit granularitet.32-bitars granularitet kommer troligen från andra processorer som ARM / Intel som GCC används för.
@MaNyYaCk: eftersom mikrokontroller, särskilt sådana med 2k ram, används i applikationer där all din minnesanvändning ska vara känd vid designtid och statiskt tilldelad.
@MaNyYaCk Att använda malloc på en liten mikrokontroller som detta ger ingen mening, [se detta] (http://electronics.stackexchange.com/questions/171257/realloc-wasting-lots-of-space-in-my-mcu/ 171581 # 171581).
Tre svar:
Tom Carpenter
2016-12-04 00:08:37 UTC
view on stackexchange narkive permalink

För den första frågan:

Det finns 2 kB SRAM. Det finns ytterligare 32 byte av CPU-register och ytterligare 64 byte av I / O-register (saker som PORTA / DDRA / etc.-register).

Lägg till allt, vi får 2048 + 32 + 64 = 2144byte adresserbart minne. Konvertera det till hexadecimalt så får du 0x860 - eller i adressvillkor 0x000 till 0x85F.

SRAM-minnet i sig är 2kB-blocket från 0x060 till 0x85F.

För den andra frågan:

malloc använder en så kallad "freelist" som bibehåller vilka bitar av minne som finns tillgängliga för allokering eller omfördelning. Den här listan lagras i samma SRAM som det minne du tilldelar och uppdateras direkt när du använder allokera minne.

Varje post i frilistan är en 16-bitars pekare, som pekar på nästa post som bildar en kedja - varje post håller reda på var nästa post är - och en 16-bitars storlek som säger hur stort det aktuella blocket är.

Som ett resultat måste varje minnesblock som tilldelats med malloc vara minst 4 byte i storlek för att lagra listposten. När du begär en enda byte minne måste den avrunda upp till fyra byte så att när minnet delas ut, finns det plats för en lista som ska lagras där.

I stället för att gå in i exakta detaljer förklaras frilistmetoden i avr-libc-dokumentationen här. Följande citat förklarar behovet

Själva frilistan upprätthålls inte som en separat datastruktur, utan snarare genom att ändra innehållet i det frigjorda minnet så att det innehåller pekare som sammanbitar bitarna. På det sättet krävs inget extra minne för att upprätthålla denna lista förutom en variabel som håller reda på det lägsta minnessegmentet som är tillgängligt för omallokering. Eftersom båda, en kedjepekare och storleken på biten måste registreras i varje bit, är den minsta bitstorleken på frilistan fyra byte

Om du inte kan ta huvudet runt (processen är inte omedelbart uppenbar) behöver du inte oroa dig.Det enkla att komma ihåg är att varje bit du malloc kommer att ha minst 4 byte i storlek, även om du bara vill ha 1.


Det är också värt att notera efter lite experiment, hur mycket minne som tilldelas verkar alltid vara det största av antingen 4 byte eller den begärda mängden + 2 byte.Om du till exempel ber om 3 byte tilldelas 5 byte.Om du ber om 8 byte får du 10.

Varför extra 2 byte tilldelas är jag osäker.Jag kan inte hitta referens till detta i avr-libc-dokumentationen.

Jag tror att de två extra byten är för fältet `sz` som lagrar storleken på den tilldelade biten (som kan skilja sig från den begärda storleken).Se avr-libc-2.0.0 `malloc.c: 176-179` där en ny bit skapas.
Så hur är det för mig att beräkna Stack och Heap?Jag menar att det finns viss dokumentation i AVR-Libc men jag har svårt att förstå varifrån variablerna för start- och Heap-slut kommer och hur man ställer in den.
Det skulle finnas en (icke-standard) biblioteksfunktion förutsatt att den passerar frilistan och tillhandahåller statistik inklusive totalstorlek och största blockstorlek.
@MaNyYaCk: titta på källkoden för malloc-funktionen.
@JDługosz Det verkar som att det jag bad om är ett mycket djupt ämne och jag måste läsa mer.All hjälp uppskattad.Tack :)
Jag rekommenderar fortfarande Knuths * The Art of Computer Programming *, §2.5.Du kan också börja med [Wikipedia] (https://en.wikipedia.org/wiki/Memory_management#DYNAMIC).
JDługosz
2016-12-04 13:55:26 UTC
view on stackexchange narkive permalink

Låt mig förklara de mer detaljerade resultat som noterats av Tom Carpenter i kommentarer:

varje begäran till malloc verkar tilldela den större av antingen 4 byte eller det erforderliga beloppet + 2 byte

Varje begäran kräver ytterligare 2 byte av omkostnader. Detta registrerar blockets size, så gratis vet vad som exakt ska återkravas. Med 1-bytes granularitet och 2K att hålla reda på behöver du 14 bitar för den här storleken. Det passar i två byte.

En nod gratislistan använder det fria minnet i sig för att hålla reda på det fria minnet. Den behöver storleken, samma som den tilldelade noden. Men det behöver också en pekare till nästa lediga nod, som tar ytterligare två byte. Så varje block som ska frigöras måste vara minst 4 byte totalt (2 byte ges för användning och 2 för storleken på det tilldelade blocket).

Så om du ber om 1 byte måste den allokera 2 och ta ytterligare 2 för overhead. Mer allmänt tar det ytterligare 2 byte för overhead och det lämnar aldrig ett fritt block som skulle vara för litet för en gratis nod. Det vill säga om du frågade efter (säg) 19 byte och gratislistan hade en nod 24 byte, kunde den inte hugga av 19 + 2 och lämna 2 + 1 bakom sig: den skulle fördela det hela trots att det är 3 byte mer än begärts.


Jag är bekant med hur högen fungerar för redan 1983 eller så läste jag Knuths The Art of Computer Programming och har implementerat detta vid flera tillfällen.

mkeith
2016-12-04 01:02:39 UTC
view on stackexchange narkive permalink

Problemet är relaterat till minnesjustering.Ofta har processorer en begränsning att när de får åtkomst till en 32-bitars datatyp måste de göra det med en adress som är en multipel av 4. Detta är bara ett exempel på en inriktningsbegränsning.

malloc () krävs av C-standarden för att returnera en adress med maximal inriktning så att NÅGON datatyp kan lagras på den adressen. malloc () vet inte vilken datatyp du ska använda adressen för.

Så förmodligen returnerar malloc () multiplar av 4 eftersom denna processor kräver det för vissa datatyper.

Den här frågan kan faktiskt passa bättre för ett programmeringsforum.

För avr-libc returnerar det faktiskt inte multiplar av 4. Om jag försöker `malloc` på en icke-multipel av 4, kommer den att öka med en icke-multipel av 4. Till exempel om jag ringer` malloc` tre gånger i radför 5 byte vardera kommer pekarna att ökas med 7 varje gång.I själva verket verkar varje förfrågan till "malloc" allokera den större av antingen 4 byte eller den erforderliga mängden + 2 byte.
@TomCarpenter, mycket intressant.Jag kommer dock att lämna mitt svar kvar, för även om det inte gäller i det här fallet tror jag att det kan vara ett användbart svar för andra som hittar denna fråga genom sökning.
@TomCarpenter Kan du hjälpa mig att förklara varför förbrukar de extra byte?Jag hade provat det.Vad är extra två byte för specifikt?


Denna fråga och svar översattes automatiskt från det engelska språket.Det ursprungliga innehållet finns tillgängligt på stackexchange, vilket vi tackar för cc by-sa 3.0-licensen som det distribueras under.
Loading...