C Programovanie

malloc v jazyku c

malloc v jazyku c
Môžete sem prísť z dvoch dôvodov: buď chcete dynamicky alokovať obsah, alebo chcete vedieť viac o tom, ako funguje malloc. V obidvoch prípadoch ste na správnom mieste! Dynamická alokácia je proces, ktorý sa deje často, ale spravidla ho nepoužívame sami: veľká väčšina programovacích jazykov spravuje pamäť za vás, pretože je to náročná práca a ak to neurobíte správne, majú to bezpečnostné dôsledky.

Ak však pracujete na C, C ++ alebo montážnom kóde alebo ak implementujete nový externý modul vo svojom obľúbenom programovacom jazyku, budete si musieť dynamické prideľovanie pamäte spravovať sami.

Čo je dynamické priradenie? Prečo potrebujem malloc?

No, vo všetkých aplikáciách, keď vytvoríte novú premennú - často sa to nazýva deklarácia premennej - na jej uloženie potrebujete pamäť. Pretože je váš počítač v súčasnej dobe moderný, môže spúšťať viac ako jednu aplikáciu súčasne, takže každá aplikácia by mala vášmu operačnému systému povedať, (tu Linux) že potrebuje také množstvo pamäte. Keď píšete tento druh kódu:

#include
#include
#define DISK_SPACE_ARRAY_LENGTH 7
void getFreeDiskSpace (int statsList [], size_t listLength)
návrat;

int main ()
/ * Obsahuje voľné miesto na disku za posledných 7 dní. * /
int freeDiskSpace [DISK_SPACE_ARRAY_LENGTH] = 0;
getFreeDiskSpace (freeDiskSpace, DISK_SPACE_ARRAY_LENGTH);
návrat EXIT_SUCCESS;

Pole freeDiskSpace vyžaduje pamäť, takže na získanie určitej pamäte budete musieť požiadať Linux o súhlas. Ako je však zrejmé pri čítaní zdrojového kódu, že budete potrebovať pole 7 int, kompilátor ho automaticky požiada o systém Linux a pridelí ho na zásobník. To v podstate znamená, že toto úložisko sa zničí, keď vrátite funkciu, kde je deklarovaná premenná. Preto to nemôžete urobiť:

#include
#include
#define DISK_SPACE_ARRAY_LENGTH 7
int * getFreeDiskSpace ()
int statisticsList [DISK_SPACE_ARRAY_LENGTH] = 0;
/ * PREČO TO ROBÍME?! statsList bude ZNIČENÝ! * /
návratové štatistikyList;

int main ()
/ * Obsahuje voľné miesto na disku za posledných 7 dní. * /
int * freeDiskSpace = NULL;
freeDiskSpace = getFreeDiskSpace ();
návrat EXIT_SUCCESS;

Teraz vidíte problém ľahšie? Potom chcete zreťaziť dva reťazce. V jazykoch Python a JavaScript by ste robili:

newStr = str1 + str2

Ale ako viete, v jazyku C to takto nefunguje. Ak chcete napríklad vytvoriť adresu URL, musíte zreťaziť dva reťazce, napríklad cestu URL a názov domény. V jazyku C máme strcat, no funguje to, iba ak máte pole s dostatkom miesta na to.

Budete v pokušení poznať dĺžku nového reťazca pomocou výrazu strlen a mali by ste pravdu. Ale potom, ako by ste požiadali Linux, aby si vyhradil toto neznáme množstvo pamäte? Kompilátor vám nemôže pomôcť: presný priestor, ktorý chcete vyhradiť, je známy iba za behu programu. Presne tam potrebujete dynamické priradenie a malloc.

Zápis mojej prvej funkcie C pomocou programu malloc

Pred napísaním kódu, malé vysvetlenie: malloc vám umožňuje prideliť konkrétny počet bajtov pre použitie vašej aplikácie. Používanie je skutočne jednoduché: zavoláte malloc s počtom bajtov, ktorý potrebujete, a vráti ukazovateľ na vašu novú oblasť, ktorú vám Linux vyhradil.

Máte iba 3 povinnosti:

  1. Skontrolujte, či malloc vracia NULL. To sa stane, keď Linux nemá dostatok pamäte na poskytnutie.
  2. Raz nepoužívané premenné uvoľnite. Inak stratíte pamäť a spomalí to vašu aplikáciu.
  3. Po uvoľnení premennej nikdy nepoužívajte pamäťovú zónu.

Ak budete dodržiavať všetky tieto pravidlá, všetko pôjde dobre a dynamické prideľovanie vám vyrieši veľa problémov. Pretože si vyberiete, kedy uvoľníte pamäť, môžete bezpečne vrátiť aj premennú pridelenú malloc. Len to nezabudnite uvoľniť!

Ak vás zaujíma, ako uvoľniť premennú, je to bezplatná funkcia. Zavolajte to rovnakým ukazovateľom, ako vás malloc vrátil, a pamäť sa uvoľní.

Ukážem vám príklad concat:

#include
#include
#include
/ *
* Pri volaní tejto funkcie nezabudnite skontrolovať, či je návratová hodnota NULL
* Ak to nemá hodnotu NULL, musíte po vrátení ukazovateľa po vyvolaní hodnoty volať zadarmo
* sa už nepoužíva.
* /
char * getUrl (const char * const baseUrl, const char * const toolPath)
size_t finalUrlLen = 0;
char * finalUrl = NULL;
/ * Kontrola bezpečnosti. * /
if (baseUrl == NULL || toolPath == NULL)
návrat NULL;

finalUrlLen = strlen (baseUrl) + strlen (toolPath);
/ * Nezabudnite na '\ 0', teda + 1. * /
finalUrl = malloc (sizeof (char) * (finalUrlLen + 1));
/ * Podľa pravidiel malloc ... * /
if (finalUrl == NULL)
návrat NULL;

strcpy (finalUrl, baseUrl);
strcat (finalUrl, toolPath);
návrat finalUrl;

int main ()
char * googleImages = NULL;
googleImages = getUrl ("https: // www.google.com "," / imghp ");
if (googleImages == NULL)
návrat EXIT_FAILURE;

puts ("URL nástroja:");
puts (googleImages);
/ * Už to nie je potrebné, uvoľnite to. * /
zadarmo (googleImages);
googleImages = NULL;
návrat EXIT_SUCCESS;

Vidíte teda praktický príklad použitia dynamických alokácií. Najprv sa vyhýbam nástrahám, ako je dávanie návratovej hodnoty getUrl priamo funkcii put. Potom si tiež nájdem čas na vyjadrenie a zdokumentovanie skutočnosti, že návratová hodnota by sa mala správne uvoľniť. Tiež všade kontrolujem NULL hodnoty, aby bolo možné bezpečne naraziť na niečo neočakávané namiesto toho, aby došlo k zlyhaniu aplikácie.

Nakoniec venujem zvýšenú pozornosť uvoľneniu premennej a následnému nastaveniu ukazovateľa na NULL. Vyhnete sa tak pokušeniu použiť - aj omylom - teraz uvoľnenú pamäťovú zónu. Ako však vidíte, je ľahké premennú uvoľniť.

Môžete si všimnúť, že som použil sizeof v malloc. Umožňuje zistiť, koľko bajtov znak používa, a objasňuje zámer v kóde, aby bol čitateľnejší. Pre char je sizeof (char) vždy rovné 1, ale ak namiesto nich použijete pole int, funguje to úplne rovnako. Napríklad, ak potrebujete rezervovať 45 int, stačí urobiť:

fileSizeList = malloc (sizeof (int) * 45);

Takto rýchlo uvidíte, koľko chcete prideliť, preto vždy odporúčam jeho použitie.

Ako funguje malloc pod kapotou?

malloc a free sú v skutočnosti funkcie zahrnuté vo všetkých programoch C, ktoré budú vo vašom mene hovoriť s Linuxom. Uľahčí to tiež dynamické priradenie, pretože Linux na začiatku neumožňuje prideľovať premenné všetkých veľkostí.

Linux poskytuje dva spôsoby, ako v skutočnosti získať viac pamäte: sbrk a mmap. Oba majú obmedzenia a jedným z nich je: môžete prideliť iba relatívne veľké sumy, napríklad 4 096 bajtov alebo 8 192 bajtov. Nemôžete požiadať o 50 bajtov, ako som to urobil v príklade, ale tiež nemôžete požiadať o 5 894 bajtov.

Toto má vysvetlenie: Linux musí udržiavať tabuľku, ktorá informuje o tom, ktorá aplikácia si vyhradila ktorú zónu pamäte. A táto tabuľka tiež využíva priestor, takže ak by každý bajt potreboval nový riadok v tejto tabuľke, bola by potrebná veľká časť pamäte. Preto je pamäť rozdelená na veľké bloky, napríklad 4 096 bajtov, a podobne, ako si nemôžete kúpiť 2 pomaranče a pol v potravinách, nemôžete požiadať o polovičné bloky.

Malloc teda vezme tieto veľké bloky a dá vám malý kúsok týchto pamäťových blokov, kedykoľvek to zavoláte. Rovnako, ak ste uvoľnili niekoľko premenných, ale nie dosť na to, aby ste ospravedlnili uvoľnenie celého bloku, systém malloc môže pri ďalšom volaní malloc blokovať a recyklovať pamäťové zóny. To má výhodu v tom, že program malloc je rýchlejší, avšak pamäť vyhradenú programom malloc sa nedá použiť v žiadnej inej aplikácii, zatiaľ čo program ho v skutočnosti momentálne nepoužíva.

Ale malloc je inteligentný: ak zavoláte malloc na pridelenie 16 MiB alebo väčšieho množstva, malloc pravdepodobne požiada Linux o plné bloky určené práve pre túto veľkú premennú pomocou mmap. Týmto spôsobom, keď budete volať zadarmo, sa pravdepodobnejšie vyhnete tomu plytvaniu priestorom. Nebojte sa, malloc robí recykláciu oveľa lepšie ako ľudia s našimi odpadkami!

Záver

Myslím, že teraz lepšie pochopíte, ako to všetko funguje. Dynamická alokácia je samozrejme veľká téma a myslím si, že o tejto téme môžeme napísať celú knihu, ale tento článok by vás mal oboznámiť s touto koncepciou všeobecne a s praktickými radami programovania.

Trackpad a ukazovateľ myši AppyMouse na obrazovke pre tablety so systémom Windows
Používateľom tabletov často chýba ukazovateľ myši, najmä keď notebooky bežne používajú. Dotykové smartphony a tablety majú veľa výhod a jediným obmedz...
Stredné tlačidlo myši nefunguje v systéme Windows 10
The stredné tlačidlo myši pomáha vám prechádzať dlhé webové stránky a obrazovky s množstvom údajov. Ak sa to zastaví, budete nakoniec používať klávesn...
Ako zmeniť ľavé a pravé tlačidlo myši na počítači so systémom Windows 10
Je úplnou normou, že všetky zariadenia počítačových myší sú ergonomicky navrhnuté pre pravákov. Existujú však dostupné myšacie zariadenia, ktoré sú šp...