Sida 1 av 3

malloc eller lokala variabler?

Postat: 6 februari 2016, 23:49:32
av jesse
Jag hittade ett program för AVR där ett antal funktioner innehåller malloc.

Vad jag inte förstår är när det är en fördel att använda malloc? Jag har aldrig någonsin använt det.

I funktionen ser det ut ungefär så här (förenklat):

Kod: Markera allt

// Function which allocates memory using malloc()

#define BYTES 8 // Size of message
uint8_t  func(uint8_t  n, uint8_t  input_data[][BYTES])
{
  uint8_t *rx_data;
  rx_data = (uint8_t *) malloc(BYTES*n);
  for (int i = 0; i<n; i++)
  {
      SPI_read(device[i], rx_data, 8); // read 8 bytes into array rx_data
      for (j = 0; j < BYTES; j++)
      {
            input_data[i][j] = rx_data[current_byte + (current_ic*BYTES_IN_REG)];
      }
      // ... do some other stuff
  }
  free(rx_data);
}
(Exemplet känns extra korkat eftersom data direkt efter inläsning skyfflas över till den globala arrayen input_data[][], så någon mellanlagring tycks för mig vara helt onödig här?)

Men frågan är - hur skiljer sig ovanstående kod mot att man istället deklarerade en lokal array i funktionen. Det borde ju skapa ett tillfälligt utrymme precis som malloc. Enda skillnaden är väl att malloc skapar utrymme i "slutet" av de globala och statiska variablerna i RAM, medans den lokala arrayen hamnar i stacken. Då slipper man även användafree(), eftersom den lokala variabeln förstörs automatiskt när den inte längre behövs.

Finns det någon fördel eller nackdel med någon av metoderna?

Kod: Markera allt

// Function which allocates memory by declaring a local variable (array)

#define BYTES 8 // Size of message
uint8_t  func(uint8_t  n, uint8_t  input_data[][BYTES])
{
  uint8_t rx_data[BYTES]; // alloc. temporary data in memory
  for (int i = 0; i<n; i++)
  {
      SPI_read(device[i], rx_data, 8); // read 8 bytes into array rx_data
      for (j = 0; j < BYTES; j++)
      {
            input_data[i][j] = rx_data[current_byte + (current_ic*BYTES_IN_REG)];
      }
      // ... do some other stuff
  }
}

Re: malloc eller lokala variabler?

Postat: 7 februari 2016, 00:28:42
av sodjan
Malloc() är väl bra om storleken inte är känd vid kompileringen utan
behöver anges dynamiskt. Däremot så är väl det något som det
brukar avrådas från på mindre 8-bitare. Rent tekniskt är det ingen
speciell skillnad efter att malloc() har allokerat minnet, men som
sagt så är det effektivare att fixa det vid kompileringen och man
får då också besked direkt om minnet räcker till eller inte.

Re: malloc eller lokala variabler?

Postat: 7 februari 2016, 00:35:20
av lillahuset
Malloc är en bra idé, men kanske inte så bra om man inte absolut måste. Du vet aldrig hur lång tid det tar att städa efter malloc. Risken för den klassiska buggen med "minnesläckage" är inte heller att leka med. Men gör man allting rätt är det utmärkt med malloc.

Re: malloc eller lokala variabler?

Postat: 7 februari 2016, 00:49:39
av Mr Andersson
Som sodjan nämnde så är den största skillnaden att du behöver inte veta storleken vid kompilering (c99 VLAs inte inräknat).
Sen om du lagrar stora variabler eller arrays på stacken så, beroende på arkitektur, kan den bli full ganska snabbt.

Men med det sagt, den där koden är ett dåligt exempel på mallocanvändning. Dels så är det ju bara 8 bytes, och dels så allokeras det mer minne än vad som behövs. (8*n när bara 8 bytes används).

Re: malloc eller lokala variabler?

Postat: 7 februari 2016, 18:47:20
av Findecanor
Beror väl på vad för slags maskin man använder. På en del kan man ha ganska begränsad stack, och att då allockera en array på stacken utan vidare kan leda att den flödar över och man får en trap, man skriver ut i oanvänt adressutrymme, maskinregister eller wrappar runt (beroende på maskin).
Funktionen malloc() kollar alltid om det finns ledigt utrymme - om inte ger den NULL. Man ska alltid kolla returvärdet från malloc() och hantera fallet när den är NULL.

Om man har extra litet programminne (8-bit AVR eller liknande) så ska man kanske inte ens länka med C-biblioteket, eller om det går, lämna delar av det utanför.

En annan sak är att arrayer på stacken med dynamisk storlek inte stödjs av vissa C-kompilatorer (kom i C99, försvann i C11-standarden) och att vissa aldrig haft det pga hur runtime-miljön är på den plattformen.
Ett känt exempel är C-kompilatorn i Microsoft Visual Studio på Windows som inte stödde det förrän bara ett par år sedan.

(Sen antar jag att du inte menade att rx_data = malloc(n * BYTES) och att använda offsets i rx_data ...)

Re: malloc eller lokala variabler?

Postat: 7 februari 2016, 19:14:12
av Nerre
Det handlar väl i det här fallet om att det är en array av vid kompileringen okänd storlek. Då kan du inte i källkoden deklararera en lokal variabel som har "rätt" storlek.

Eller menar du att du kan skriva om koden på ett sätt så den fungerar även utan malloc?

Re: malloc eller lokala variabler?

Postat: 7 februari 2016, 22:06:07
av sodjan
Var inte det andra exemplet utan malloc() !?

Re: malloc eller lokala variabler?

Postat: 7 februari 2016, 23:05:12
av jesse
Tack för svaren. Nu börjar jag förstå bättre. :)

Nerres svar sammanfattar väl skillnaden bäst. Jag har inte tidigare tänkt på att lokala variabler (eller arrayer) måste ha bestämd storlek från början, men det måste de ju förstås.

Sodjan: andra exemplet var mitt försök att göra samma sak som det första, fast utan malloc. Jag har tydligen gjort fel, för jag definierar där en array med fast storlek, men i första exemplet var det ju en variabel storlek.

Men i sammanhang med microcontrollers brukar jag tänka att minnet måste räcka till i alla tänkbara situationer för att systemet ska vara tillförlitligt. Då är det meningslöst att använda dynamisk minnesallokering - jag skapar i så fall hellre en stor array från början som kan rymma största tänkbara mängd data. Antag att vi ska läsa av x antal sensorer. Varje resultat innehåller 8 bytes. x kan variera mellan 1 och 100. Istället för att hååa på att skapa nytt minne hela tiden beroende på vad x för tillfället råkar vara, så dimensionerar jag arrayen direkt som

uint8_t result[100][ 8 ];

Får inte det plats i minnet så har lag för lite minne. Om sedan i praktiken bara 8 bytes eller 800 bytes används spelar ju ingen roll.

Re: malloc eller lokala variabler?

Postat: 7 februari 2016, 23:20:22
av sodjan
Absolut, Nerre har helt rätt, eftersom det var samma sak som jag skrev lite tidigare... :-)

Och visst, det finns en fördel med att få minnesbehovet klargjort och verifierat
redan vid kompileringen för att inte få problem senare. Ett problem kan ju vara
ifall du har behov av en lokal/temporär array i flera olika funktioner. Om varje
rutin då gör sin egen malloc/free så kolliderar det aldrig, men å andra sidan så
blir minnesbehovet svårare att beräkna i förväg.

Sen så finns det ju alltid en gräns där man måste fråga sig om man har valt
rätt plattform från början. Fixar den valda processorn de olika kraven från
applikationen överhuvudtaget?

Slutligen finns ju även prestandasidan av det. Att göra malloc()/free()
dynamiskt tar så klart väldigt mycket mer tid än att använda redan
allokerade variabler/arrayer.

Re: malloc eller lokala variabler?

Postat: 8 februari 2016, 07:23:13
av Nerre
Ja tittar man på större program som ordbehandlare eller webbläsare så kan man ju inte gärna allokera allt tänkbart minnesbehov från början (fast jag undrar om det inte var så Mac OS funkade förr?).

För mikrocontrollers är ju situationen lite annan.

En fördel med att köra malloc/free är ju att minnet är "ledigt" när man inte använder det. Så blir det iofs med lokala variabler också, men med malloc/free så kan du om du kör flera processer parallellt (t.ex. interrupthantering) prova om minnet är ledigt och om det inte är det så väntar du och försöker lite senare (ungefär).

Beroende på processor så kan det väl också finnas begränsningar i storleken på lokala variabler?

Så det är "som vanligt" väldigt mycket "det beror på".

Re: malloc eller lokala variabler?

Postat: 8 februari 2016, 09:28:05
av sodjan
Ja, det stämmer ju i det generella fallet. Men eftersom det redan i första
meningen i första inlägget stod "Jag hittade ett program för AVR..." så
får vi väl utgå från den typen av miljöer.

Re: malloc eller lokala variabler?

Postat: 8 februari 2016, 09:48:46
av Nerre
Frågan var ju
Vad jag inte förstår är när det är en fördel att använda malloc?
och som jag försökte få fram så är svaret på frågan: "Det beror på"

Re: malloc eller lokala variabler?

Postat: 8 februari 2016, 10:03:31
av sodjan
Ja, det är ju alltid rätt svar... :-)

Re: malloc eller lokala variabler?

Postat: 8 februari 2016, 10:13:24
av pbgp
Nu är jag inte så hemma på mikrokontrollrar. Men jag kan tänka mig att det finns miljöer där man har begränsat med stack men en ganska stor heap (som det utrymme som malloc sköter ibland kallas).

I det fallet skulle en funktion som anropas långt ner i en kedja av funktionsanrop riskera att få slut på minne snabbare om all data läggs på stacken. Särskilt om funktionen är rekursiv.

Re: malloc eller lokala variabler?

Postat: 8 februari 2016, 11:10:27
av Nerre
Ja det var det där med stack kontra heap som jag tänkte på när jag skrev
Beroende på processor så kan det väl också finnas begränsningar i storleken på lokala variabler?
Men jag kom inte på rätt terminologi på grejerna.