A jeste dalsi poznamky
kazda dynamicka alokace pameti (na halde, tedy pomoci new/malloc) ve skutecnosti alokuje pamet minimalne o velikosti 2 ukazatelu (4B na arduinu), protoze pri uvolneni te pameti se tam musi zapsat kolik te pameti bylo uvolneno a kde je dalsi volny blok, aby tu pamet slo posleze opet pridelit.
Nektere implementace delaji take to, ze alokuji pamet o pointer delsi a vrati ukazatel az za ten pointer, pricem v tom miste PRED vracenym ukazatelem ulozi delku alokovane pameti pro nasledne "free(x)".
Pokud prekladac pouziva zarovnavani delsich promennych/struktur na 2/4/8/16B, tak je zaruceno, ze pointer vraceny malloc zacina na teto hranici a delka alokovane pameti se vhodne zaokrouhli nahoru.
man malloc: The malloc() and calloc() functions return a pointer to the allocated memory, which is suitably aligned for any built-in type.
Nastesti na atmega328 se zarovnava na 1B, ale jsou bezne architektury (treba na 8B) a tam uz to chraje velkou roli.
Kód: Vybrat vše
#include "MemoryFree.h"
char *a;
long *l;
long long *ll;
void setup(){
Serial.begin(9600);
Serial.print("free ");
Serial.println(freeMemory());
a=(char *)malloc(1);
*a='a';
Serial.print("free -");
Serial.print(sizeof(char));
Serial.print(" = ");
Serial.println(freeMemory());
l=(long *)malloc(sizeof(long));
*l='1';
Serial.print("free -");
Serial.print(sizeof(long));
Serial.print(" = ");
Serial.println(freeMemory());
ll=(long long*)malloc(sizeof(long long));
*ll='1';
Serial.print("free -");
Serial.print(sizeof(long long));
Serial.print(" = ");
Serial.println(freeMemory());
}
void loop(){
if (*a=='a') *a='b'; else *a='a';
*l=*l+1;
*ll=*ll+1;
}
free 1807
free -1 = 1803
free -4 = 1797
free -8 = 1787
tady je videt, ze se ke kazde alokaci prida jen 2B delka pred ni samotnou
Pokud tedy potrebujes alokovat spoustu 1B promennych a vis, ze je budes alokovat naraz a uvolnovat naraz, je lepsi je alokovat jako pole a pak ty jednotlive pointery dat na jednotlive prvky pole. (rezie je 3x vetsi, nez uzita pamet)
Ne kazdy pointer vsak nutne ukazuje na zacatek alokovaneho bloku, takze nelze zavolat "free" na libovolny pointer, ale jen ta takovy, ktery ukazuje na stejne misto, jako ukazoval pointer vraceny nejakym malloc (trivialni dusledek toho, ze muzes alokovat treba pole znaku, nasypat tam retezec, a pak pouzivat ukazatele na znak aby ukazovaly na zacatky slov v tom retezci - ale nemuzes dealokovat "3 slovo teto vety", protoze byl alokovan cely odstavec.
take si muzes precist
https://en.wikipedia.org/wiki/Memory_ma ... allocation
Take se da udelat to, ze si na zacatku alokujes (at uz dynamicky, nebo jako staticke pole) celou pamet (az na misto potrebne pro zasobnik) (nebo ji dokonce nealokujes ale jen tak pouzivas, pokud je cely kod tvuj a zadna knihovna nepouziva malloc) a udelas si vlastni spravu pameti po svem - pak tam muzes mit nejruznejsi vychytavky navic, ale taky to muze byt neskutecny opruz spravovat. Na druhou stranu spousta tech vychytavek jde udelat i tim, ze se podivas, jak konktertne je sprava pameti udelana na tve cilove platforme a hrabes se ji ve vnitrnich "skrytych" zalezitostech.
Takze pokud vis, ze fuknce dostala ukazatel vraceny z malloc, tak vis, ze o dva byte niz v pameti najdes i delku te alokace (bud jako unint16_t, nebo jako ukazatel na dalsi zabrany kus a delku ziskas odectenim tech adres). Ze je to neprenosne na jinou platformu netreba zminovat.