C Programování

malloc v jazyce c

malloc v jazyce c
Můžete sem přijít ze dvou důvodů: buď chcete dynamicky přidělit obsah, nebo chcete vědět více o tom, jak malloc funguje. V obou případech jste na správném místě! Dynamická alokace je proces, který se děje často, ale obecně jej sami nepoužíváme: drtivá většina programovacích jazyků spravuje paměť za vás, protože je to těžká práce, a pokud to neuděláte správně, mají to bezpečnostní důsledky.

Pokud však děláte C, C ++ nebo montážní kód, nebo pokud implementujete nový externí modul ve svém oblíbeném programovacím jazyce, budete si muset dynamickou alokaci paměti spravovat sami.

Co je dynamická alokace? Proč potřebuji malloc?

Ve všech aplikacích, když vytvoříte novou proměnnou - často se tomu říká deklarace proměnné - k uložení potřebujete paměť. Vzhledem k tomu, že váš počítač je v moderní době, může spouštět více než jednu aplikaci najednou, takže každá aplikace by měla sdělit váš operační systém (zde Linux) že potřebuje takové množství paměti. Když píšete tento druh kódu:

#zahrnout
#zahrnout
#define DISK_SPACE_ARRAY_LENGTH 7
void getFreeDiskSpace (int statsList [], size_t listLength)
vrátit se;

int main ()
/ * Obsahuje volné místo na disku za posledních 7 dní. * /
int freeDiskSpace [DISK_SPACE_ARRAY_LENGTH] = 0;
getFreeDiskSpace (freeDiskSpace, DISK_SPACE_ARRAY_LENGTH);
vrátit EXIT_SUCCESS;

Pole freeDiskSpace potřebuje paměť, takže budete muset požádat Linux o schválení, abyste získali trochu paměti. Jak je však při čtení zdrojového kódu zřejmé, že budete potřebovat pole 7 int, kompilátor jej automaticky požádá o Linux a přidělí jej na zásobníku. To v podstatě znamená, že toto úložiště bude zničeno, když vrátíte funkci, kde je deklarována proměnná. Proto to nemůžete udělat:

#zahrnout
#zahrnout
#define DISK_SPACE_ARRAY_LENGTH 7
int * getFreeDiskSpace ()
int statisticsList [DISK_SPACE_ARRAY_LENGTH] = 0;
/ * PROČ TO DĚLÁME?! statsList bude ZNIČENO! * /
návratové statistikyList;

int main ()
/ * Obsahuje volné místo na disku za posledních 7 dní. * /
int * freeDiskSpace = NULL;
freeDiskSpace = getFreeDiskSpace ();
vrátit EXIT_SUCCESS;

Problém teď uvidíte snadněji? Potom chcete zřetězit dva řetězce. V Pythonu a JavaScriptu byste udělali:

newStr = str1 + str2

Ale jak víte, v C to takto nefunguje. Chcete-li například vytvořit adresu URL, musíte zřetězit dva řetězce, například cestu URL a název domény. V C máme strcat, správně, ale funguje to pouze v případě, že máte pole s dostatečným prostorem pro něj.

Budete v pokušení poznat délku nového řetězce pomocí strlen a měli byste pravdu. Jak byste ale mohli požádat Linux o rezervaci tohoto neznámého množství paměti? Kompilátor vám nemůže pomoci: přesný prostor, který chcete přidělit, je znám pouze za běhu. Přesně tam potřebujete dynamickou alokaci a malloc.

Psaní mé první C funkce pomocí malloc

Než začnete psát kód, malé vysvětlení: malloc vám umožňuje přidělit konkrétní počet bajtů pro použití vaší aplikace. Používání je opravdu jednoduché: zavoláte malloc s počtem bytů, který potřebujete, a vrátí ukazatel na vaši novou oblast, kterou vám Linux rezervoval.

Máte pouze 3 povinnosti:

  1. Zkontrolujte, zda malloc vrátí NULL. To se stane, když Linux nemá dostatek paměti k poskytnutí.
  2. Osvoboďte své proměnné, jakmile jsou nepoužívané. Jinak ztratíte paměť a vaše aplikace se zpomalí.
  3. Po uvolnění proměnné nikdy nepoužívejte paměťovou zónu.

Pokud budete dodržovat všechna tato pravidla, vše půjde dobře a dynamická alokace vám vyřeší mnoho problémů. Protože si vyberete, kdy uvolníte paměť, můžete také bezpečně vrátit proměnnou přidělenou malloc. Jen to nezapomeňte uvolnit!

Pokud vás zajímá, jak uvolnit proměnnou, je to bezplatná funkce. Nazvěte to stejným ukazatelem, než který vám malloc vrátil, a paměť se uvolní.

Ukážu vám příklad concat:

#zahrnout
#zahrnout
#zahrnout
/ *
* Při volání této funkce nezapomeňte zkontrolovat, zda je návratová hodnota NULL
* Pokud to není NULL, musíte po vráceném ukazateli jednou volat hodnotu zdarma
* se již nepoužívá.
* /
char * getUrl (const char * const baseUrl, const char * const toolPath)
size_t finalUrlLen = 0;
char * finalUrl = NULL;
/ * Bezpečnostní kontrola. * /
if (baseUrl == NULL || toolPath == NULL)
návrat NULL;

finalUrlLen = strlen (baseUrl) + strlen (toolPath);
/ * Nezapomeňte na '\ 0', tedy + 1. * /
finalUrl = malloc (sizeof (char) * (finalUrlLen + 1));
/ * Dodržování pravidel 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ástroje:");
puts (googleImages);
/ * Už to není potřeba, uvolněte to. * /
zdarma (googleImages);
googleImages = NULL;
vrátit EXIT_SUCCESS;

Uvidíte tedy praktický příklad použití dynamických alokací. Nejprve se vyhýbám nástrahám, jako je dávání návratové hodnoty getUrl přímo do funkce funkce. Pak si také udělám čas na komentář a zdokumentování skutečnosti, že návratová hodnota by měla být správně uvolněna. Také kontroluji hodnoty NULL všude, takže lze neočekávaně zachytit cokoli neočekávaného namísto havárie aplikace.

Nakonec věnuji zvláštní pozornost uvolnění proměnné a následnému nastavení ukazatele na NULL. Tím se vyhnete pokušení použít - i omylem - nyní uvolněnou paměťovou zónu. Ale jak vidíte, je snadné uvolnit proměnnou.

Můžete si všimnout, že jsem použil velikost v malloc. Umožňuje zjistit, kolik bajtů znak používá, a objasňuje záměr v kódu, aby byl čitelnější. Pro char je sizeof (char) vždy rovno 1, ale pokud místo toho použijete pole int, funguje to úplně stejně. Například pokud potřebujete rezervovat 45 int, stačí udělat:

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

Tímto způsobem rychle zjistíte, kolik chcete přidělit, proto vždy doporučuji jeho použití.

Jak funguje malloc pod kapotou?

malloc a free jsou ve skutečnosti funkce obsažené ve všech programech C, které za vás budou mluvit s Linuxem. Také to usnadní dynamickou alokaci, protože na začátku Linux neumožňuje alokovat proměnné všech velikostí.

Linux ve skutečnosti poskytuje dva způsoby, jak získat více paměti: sbrk a mmap. Oba mají omezení a jedním z nich je: můžete přidělit pouze relativně velké částky, například 4096 bajtů nebo 8192 bajtů. Nemůžete požadovat 50 bajtů, jako jsem to udělal v příkladu, ale také nemůžete požadovat 5 894 bajtů.

To má vysvětlení: Linux musí udržovat tabulku, ve které je uvedeno, která aplikace má vyhrazenou paměťovou zónu. A tato tabulka také využívá prostor, takže pokud by každý bajt potřeboval nový řádek v této tabulce, byla by potřeba velká část paměti. Proto je paměť rozdělena do velkých bloků, například 4 096 bajtů, a podobně jako si nemůžete koupit 2 pomeranče a půl v potravinách, nemůžete požádat o poloviční bloky.

Malloc tedy vezme tyto velké bloky a dá vám kousek těchto paměťových bloků, kdykoli to zavoláte. Pokud jste uvolnili několik proměnných, ale ne natolik, abyste ospravedlnili uvolnění celého bloku, systém malloc může při dalším volání malloc blokovat a recyklovat paměťové zóny. To má tu výhodu, že malloc je rychlejší, ale paměť vyhrazenou malloc nelze použít v žádné jiné aplikaci, zatímco program ji aktuálně ve skutečnosti nepoužívá.

Ale malloc je chytrý: pokud zavoláte malloc alokovat 16 MiB nebo velké množství, malloc pravděpodobně požádá Linux o plné bloky vyhrazené právě pro tuto velkou proměnnou pomocí mmap. Tímto způsobem, když zavoláte zdarma, se pravděpodobně vyhnete plýtvání prostorem. Nebojte se, malloc odvádí mnohem lepší práci v recyklaci než lidé s našimi odpadky!

Závěr

Myslím, že teď byste měli lépe pochopit, jak to všechno funguje. Dynamická alokace je samozřejmě velkým tématem a myslím, že na toto téma můžeme napsat celou knihu, ale tento článek by vám měl usnadnit všeobecný koncept i praktické rady ohledně programování.

Hry HD remasterované hry pro Linux, které nikdy dříve neměly vydání Linuxu
HD remasterované hry pro Linux, které nikdy dříve neměly vydání Linuxu
Mnoho vývojářů a vydavatelů her přichází s HD remasterem starých her, aby prodloužili životnost franšízy, prosím fanoušky, kteří požadují kompatibilit...
Hry Jak používat AutoKey k automatizaci linuxových her
Jak používat AutoKey k automatizaci linuxových her
AutoKey je nástroj pro automatizaci stolních počítačů pro systémy Linux a X11, programovaný v programech Python 3, GTK a Qt. Pomocí jeho funkcí skript...
Hry Jak zobrazit počítadlo FPS v linuxových hrách
Jak zobrazit počítadlo FPS v linuxových hrách
Hraní na Linuxu získalo velký tlak, když společnost Valve v roce 2012 oznámila podporu systému Linux pro klienta Steam a jejich hry. Od té doby se mno...