Správná alokace paměti

Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Uživatelský avatar
gilhad
Příspěvky: 851
Registrován: 07 bře 2018, 11:22

Re: Správná alokace paměti

Příspěvek od gilhad » 06 kvě 2018, 13:49

Taky jsem potreboval mit vedle sebe Ceckovy kod a assembler pro Arduino, tak jsem se zeptal a bylo mi odpovezeno:

https://arduino.stackexchange.com/quest ... or-library

Uživatelský avatar
gilhad
Příspěvky: 851
Registrován: 07 bře 2018, 11:22

Re: Správná alokace paměti

Příspěvek od gilhad » 06 kvě 2018, 14:27

Jeste dva hutne odkazy :)
(jak se zarovnavaji datove typy v C a kam mizi pamet - pozor uvazuje C na klasickem stroji, kde int je 4B, na arduinu je int 2B ale s touto vyhradou plati vse zde recene)
http://www.catb.org/esr/structure-packing/

kdyz se kopiruji ukazatele, tak uvolneni jedne kopie uvolni pochopitelne danou oblast pameti a vsechny ostatni kopie ukazuji do uvolneneho mista cili trik s "free(x);x=NULL" nemusi byt vzdy dostacujici :

http://blog.zhangliaoyuan.com/blog/2013 ... -language/

Uživatelský avatar
gilhad
Příspěvky: 851
Registrován: 07 bře 2018, 11:22

Re: Správná alokace paměti

Příspěvek od gilhad » 06 kvě 2018, 15:53

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.

michal123
Příspěvky: 8
Registrován: 02 kvě 2018, 19:22

Re: Správná alokace paměti

Příspěvek od michal123 » 06 kvě 2018, 16:13

http://www.catb.org/esr/structure-packing/
"Rather, each type except char has an alignment requirement;" znamená, že pokud chci rychlý přístup do paměti, pak musí být zarovnaná takže libovolného typu krom char (týká se to i polí charů?), pokud ale nepotřebuji rychlost, měl bych používat char co nejvíce abych vyplnil a nevytvářel mezery v paměti.(platí to i pro AVR?)

proč char? také unsigned char? proč se používá char s kapacitou -128 - 127 když ascii nemá záporné? proč nepoužívat pouze unsigned char když by spíše mělo jít o hodnoty 0 - 255?

když jde o ascii, možná i rozšířenou, jaký typ používat? jsou pak používat funkce jako strcpy()?


Co se týče porovnávání kódu tak to nechám na později, už jen kvůli rozsáhlosti kde bych musel hledat kde která část začíná, optimalizovat tedy budu až to bude funkční (a bude čas navíc, nebo nedostatek prostředků)

Uživatelský avatar
gilhad
Příspěvky: 851
Registrován: 07 bře 2018, 11:22

Re: Správná alokace paměti

Příspěvek od gilhad » 06 kvě 2018, 16:44

Spis jde o to, ze na spouste architektur (teda zejmena 16/32/64 bitovych) jsou strojove instrukce pro praci s delsimi typy staveny tak, ze jejich argumenty musi byt zarovnane na delku toho typu (16b typ se da cist pouze ze sudych adres, 32b typ pouze z adres delitelnych 4, ...) protoze to tak je zadratovane v HW (protoze to tak jde zadratovat vyrazne efektivneji).
Takze pokud bys umistil 64b promennou na lichou adresu, tak ji musis nacist po jednotlivych bytech a pak bud poskladat a provest na ni rychlou 64b instrukci a jeji vysledek preskladat zase zpet, nebo ji zpracovat spoustou 8b instrukci, coz je pomale a navic nektere sofistikovanejsi funkce proste neji 8b variantu (a cache ctou cele dlouhe zarovnane radky - kdyz zpracovavas spatne zarovnanou promennou, tak se do cache nacte jako jeden blok jeji dolni cast (a nejaky bordel) a jako druhy blok jeji horni cast (a nejaky bordel) - a cache jsou male ale rychle)

Takze tady jde jazyk na ruku prekladaci, ktery jde na ruku hardware.

Zaroven to neni takove omezeni, protoze vetsinou mas tech dlouhych promennych hodne (pole) a jakmile je zarovnany zacatek pole, jsou zarovnane i vsechny prvky v tom poli.

char vs. unsigned char - oboji je to 8b, historicky na tom nezalezelo, ASCII je pouze pro 0..127, takze se to dost zamenovalo s tim, co pozdeli bylo zvano short int, int8_t, uint8_t a z nejakeho duvodu bylo vyhodnejsi ho mit tehdy znaminkovy a "jednou v norme, navzdy v norme" zmena by mohla rozbit spoustu stavajicich programu a neprinesla by zadnou velkou vyhodu krome estetickeho citeni.

strcpy a spol kopiruji retezce ukoncene znakem \0 - prekvapive 0 je nula jak pro signed tak unsigned, takze s tim zadny problem nemaji.

ASCII is the American Standard Code for Information Interchange. It is a 7-bit code.

Kdyz jde o ASCII , je to jedno, protoze ASCII je definovana pouze pro 0..127. znaky 128..255 NEJSOU ASCII. (casto je pouzivaly rizna narodni rozsireni, navzajem nekoordinovana a zcela nekompatibilni - pro cestinu napriklad mame minimalne 3 nekompatibilni kodovani znaku s nabodenicky, kazde je soucastni jine platne normy. Pokud chces text mimo ASCII pouzivej UNICODE (nejlepe UTF-8) a smir se s tim, ze jedno pismenko je vic bytu (mimochodem ASCI znaky od 32 do 127 (od ' ' po '~' a tedy vsechny takzvane tistitelne) jsou v unicode kodovany jako cisla 32-127 se stejnym vyznamem, takze tento text je citelny jak v ASCII, tak v UNICODE se stejnym vysledkem).

UNICODE je tu s nami uz od konce minuleho milenia, pouzivat pro narodni texty cokoli jineho je archaizmus a znacna sance, ze se to nekde nezobrazi spravne.

michal123
Příspěvky: 8
Registrován: 02 kvě 2018, 19:22

Re: Správná alokace paměti

Příspěvek od michal123 » 16 kvě 2018, 18:39

Děkuji moc za odpovědi, problémy s pamětí se zdají být zatím vyřešené.
(založím dalaší vlákno, nevíte náhodou o knihovně/kódu pro arduino abych mohl jedním procesorem naprogramovat druhý přes serial? kdysi jsem to zkoušel a nějak jsem uspěl ale nic moc)

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 1 host