C programozás

malloc c nyelven

malloc c nyelven
Két okból jöhet ide: vagy dinamikusan szeretne tartalmat osztani, vagy többet szeretne tudni a malloc működéséről. Mindkét esetben jó helyen jársz! A dinamikus allokáció egy olyan folyamat, amely nagyon sokszor előfordul, de általában nem mi magunk használjuk: a programozási nyelvek túlnyomó többsége kezeli a memóriát az Ön számára, mivel ez nehéz feladat, és ha nem sikerül megfelelően elvégeznie, vannak biztonsági vonatkozások.

Ha azonban C, C ++ vagy összeállítási kódot hajt végre, vagy ha új külső modult vezet be a kedvenc programozási nyelvén, akkor magának kell kezelnie a dinamikus memória-allokációt.

Mi a dinamikus elosztás? Miért van szükségem mallocra?

Nos, minden alkalmazásban, amikor új változót hoz létre - gyakran változó deklarálásának hívják - memóriára van szüksége a tárolásához. Mivel a számítógép napjainkban van, egyszerre több alkalmazást is futtathat, ezért minden alkalmazásnak tájékoztatnia kell az operációs rendszert (itt Linux) hogy ekkora memóriára van szüksége. Ilyen típusú kód megírásakor:

#include
#include
#define DISK_SPACE_ARRAY_LENGTH 7
void getFreeDiskSpace (int statsList [], size_t listLength)
Visszatérés;

int main ()
/ * Az elmúlt 7 nap szabad lemezterületét tartalmazza. * /
int freeDiskSpace [DISK_SPACE_ARRAY_LENGTH] = 0;
getFreeDiskSpace (freeDiskSpace, DISK_SPACE_ARRAY_LENGTH);
visszatér EXIT_SUCCESS;

A freeDiskSpace tömbnek memóriára van szüksége, így a Linux megszerzéséhez jóváhagyást kell kérnie a memória megszerzéséhez. Mivel azonban a forráskód olvasásakor nyilvánvaló, hogy szükség lesz egy 7 int tömbre, a fordító automatikusan kéri a Linuxtól, és kiosztja a veremben. Ez alapvetően azt jelenti, hogy ez a tároló megsemmisül, amikor visszaadja a függvényt, ahol a változó deklarálva van. Ezért nem teheti meg:

#include
#include
#define DISK_SPACE_ARRAY_LENGTH 7
int * getFreeDiskSpace ()
int statsList [DISK_SPACE_ARRAY_LENGTH] = 0;
/ * MIÉRT CSINÁLUNK?! A statsList elpusztul! * /
return statsList;

int main ()
/ * Az elmúlt 7 nap szabad lemezterületét tartalmazza. * /
int * freeDiskSpace = NULL;
freeDiskSpace = getFreeDiskSpace ();
visszatér EXIT_SUCCESS;

Most könnyebben látja a problémát? Ezután két húrt kíván összefűzni. A Python és a JavaScript használatával:

newStr = str1 + str2

De mint tudod, C-ben ez nem így működik. Tehát például egy URL létrehozásához két karakterláncot kell összefűznie, például az URL elérési útját és a domain nevet. A C-ben strcat-t használunk, igaz, de ez csak akkor működik, ha van egy tömb, amelyhez van elég hely.

A strlen használatával megkísérli megismerni az új karakterlánc hosszát, és igaza lesz. De akkor hogyan kéri a Linuxot, hogy foglalja le ezt az ismeretlen memóriamennyiséget? A fordító nem tud segíteni: a lefoglalni kívánt terület csak futás közben ismert. Pontosan itt van szüksége dinamikus elosztásra és mallocra.

Az első C funkcióm írása malloc segítségével

A kód írása előtt egy kis magyarázat: a malloc lehetővé teszi, hogy egy bizonyos számú bájtot rendeljen hozzá az alkalmazás használatához. Használata nagyon egyszerű: felhívja a mallocot a szükséges bájtok számával, és egy mutatót ad vissza az új területére, amelyet a Linux fenntartott Önnek.

Csak 3 felelőssége van:

  1. Ellenőrizze, hogy a malloc NULL értéket ad-e vissza. Ez akkor történik, amikor a Linux nem rendelkezik elegendő memóriával a rendelkezésre bocsátáshoz.
  2. Szabadítsa meg a változóit, ha nem használja. Ellenkező esetben pazarolja a memóriát, és ez lelassítja az alkalmazást.
  3. Soha ne használja a memóriazónát a változó felszabadítása után.

Ha betartja ezeket a szabályokat, akkor minden jól fog menni, és a dinamikus elosztás sok problémát megold. Mivel a memória felszabadításakor dönt, biztonságosan visszaadhatja a malloc-tal lefoglalt változót is. Csak ne felejtsd el felszabadítani!

Ha kíváncsi arra, hogyan szabadítson ki egy változót, az az ingyenes funkcióval rendelkezik. Ugyanazzal a mutatóval hívhatja, mint amilyenre a malloc visszatért, és a memória felszabadul.

Hadd mutassam meg a rövid példával:

#include
#include
#include
/ *
* A funkció meghívásakor ne felejtse el ellenőrizni, hogy a visszatérési érték NULL-e
* Ha nem NULL, akkor az értéket egyszer ingyenesen kell hívnia a visszaküldött mutatóra
* már nem használatos.
* /
char * getUrl (const char * const baseUrl, const char * const toolPath)
size_t finalUrlLen = 0;
char * finalUrl = NULL;
/ * Biztonsági ellenőrzés. * /
if (baseUrl == NULL || toolPath == NULL)
return NULL;

finalUrlLen = strlen (baseUrl) + strlen (toolPath);
/ * Ne felejtsd el a '\ 0' jelet, ezért a + 1-et. * /
finalUrl = malloc (sizeof (char) * (finalUrlLen + 1));
/ * A malloc-szabályok betartása ... * /
if (finalUrl == NULL)
return NULL;

strcpy (finalUrl, baseUrl);
strcat (finalUrl, toolPath);
return finalUrl;

int main ()
char * googleImages = NULL;
googleImages = getUrl ("https: // www.Google.com "," / imghp ");
if (googleImages == NULL)
visszatér EXIT_FAILURE;

put ("Eszköz URL:");
put (googleImages);
/ * Már nincs rá szükség, szabadítsd fel. * /
ingyenes (googleImages);
googleImages = NULL;
visszatér EXIT_SUCCESS;

Tehát gyakorlati példát lát a dinamikus allokációk használatára. Először is kerülöm az olyan buktatókat, mint például a getUrl visszatérési érték megadása egyenesen a put funkcióhoz. Ezután arra is szánok időt, hogy kommentáljam és dokumentáljam a tényt, hogy a visszatérési értéket megfelelően szabadítsák fel. Azt is ellenőrizem, hogy mindenhol vannak-e NULL értékek, így bármi váratlan dolog biztonságosan elkapható az alkalmazás összeomlása helyett.

Végül különös gondot fordítok a változó felszabadítására, majd a mutató NULL értékre állítására. Ezzel elkerülhető az a kísértés, hogy - akár tévedésből - használja a most felszabadult memóriazónát. De mint láthatja, könnyen felszabadítható egy változó.

Észreveheti, hogy malloc-ban használtam a sizeof-ot. Ez lehetővé teszi annak megismerését, hogy egy karakter hány bájtot használ, és tisztázza a kód szándékát, így az olvashatóbb. A char esetében a sizeof (char) mindig egyenlő 1-vel, de ha helyette int tömböt használsz, pontosan ugyanúgy működik. Például, ha 45 intet kell lefoglalnia, tegye a következőket:

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

Így gyorsan láthatja, hogy mennyit szeretne kiosztani, ezért mindig ajánlom a használatát.

Hogyan működik malloc a motorháztető alatt?

A malloc és a free valójában az összes C program részét képezi, amelyek az Ön nevében beszélnek a Linuxszal. Ez megkönnyíti a dinamikus elosztást is, mert kezdetben a Linux nem teszi lehetővé minden méretű változó kiosztását.

A Linux kétféle módon kínál további memóriát: sbrk és mmap. Mindkettőnek vannak korlátai, és az egyik az: csak viszonylag nagy összegeket tud kiosztani, például 4096 bájt vagy 8 192 bájt. Nem kérhet 50 bájtot, mint ahogy a példában tettem, de nem is kérhet 5894 bájtot.

Ennek magyarázata van: A Linuxnak táblázatot kell vezetnie, ahol megmondja, hogy melyik alkalmazás melyik memóriazónát foglalták le. És ez a tábla is helyet foglal, így ha minden bájtnak új sorra lenne szüksége ebben a táblázatban, akkor nagy memóriára lenne szükség. Ezért van az, hogy a memória nagy blokkokban van felosztva, például 4096 bájt, és hasonlóan ahhoz, hogy 2 és másfél narancsot nem lehet élelmiszerboltban vásárolni, nem lehet fél blokkot kérni.

Tehát a malloc elveszi ezeket a nagy blokkokat, és ad egy kis szeletet ezekből a memória blokkokból, amikor csak hívja. Valamint, ha kevés változót szabadított fel, de nem elégséges egy teljes blokk felszabadításához, a malloc rendszer blokkokat tarthat és újrahasznosíthatja a memóriazónákat, amikor újra felhívja a mallocot. Ennek az az előnye, hogy a malloc gyorsabbá válik, azonban a malloc által fenntartott memória nem használható fel más alkalmazásokban, miközben a program jelenleg nem használja a valóságban.

De a malloc okos: ha felhívod a mallocot, hogy 16 MiB-t vagy nagy összeget allokálj, akkor a malloc valószínűleg a teljes váltókat kéri a Linux-tól, csak erre a nagy változóra szánva az mmap használatával. Így, ha ingyenesen hív, akkor nagyobb valószínűséggel elkerülhető a helypazarlás. Ne aggódjon, a malloc sokkal jobb munkát végez az újrahasznosítás terén, mint az emberek a szeméttel!

Következtetés

Azt hiszem, most már jobban megérti, hogy mindez hogyan működik. Természetesen a dinamikus allokáció nagy téma, és úgy gondolom, hogy teljes könyvet írhatunk a témáról, de ez a cikk megkönnyíti a koncepció fogalmát mind általában, mind a gyakorlati programozási tanácsokkal.

Microsoft Sculpt Touch vezeték nélküli egér áttekintés
Nemrég olvastam a Microsoft Sculpt Touch vezeték nélküli egér és úgy döntött, hogy megveszi. Egy ideig használat után úgy döntöttem, hogy megosztom ve...
AppyMouse képernyős Trackpad és egérmutató a Windows táblagépekhez
A táblagép-felhasználók gyakran hiányolják az egérmutatót, különösen akkor, ha szokták használni a laptopokat. Az érintőképernyős okostelefonok és táb...
Az egér középső gombja nem működik a Windows 10 rendszerben
A középső egérgomb segít átgörgetni a hosszú weboldalakat és a sok adatot tartalmazó képernyőket. Ha ez leáll, akkor a billentyűzet segítségével görge...