C Programmēšana

malloc c valodā

malloc c valodā
Jūs varat ierasties šeit divu iemeslu dēļ: vai nu vēlaties dinamiski piešķirt saturu, vai arī vēlaties uzzināt vairāk par malloc darbību. Jebkurā gadījumā jūs esat īstajā vietā! Dinamiskā piešķiršana ir process, kas notiek daudz, taču parasti mēs paši to neizmantojam: lielākā daļa programmēšanas valodu pārvalda atmiņu jums, jo tas ir grūts darbs, un, ja jūs to nedarāt pareizi, pastāv drošības problēmas.

Tomēr, ja veicat C, C ++ vai montāžas kodu vai ieviešat jaunu ārējo moduli iecienītākajā programmēšanas valodā, jums pašam būs jāpārvalda dinamiskās atmiņas piešķiršana.

Kas ir dinamisks sadalījums? Kāpēc man vajag mallocu?

Nu, visās lietojumprogrammās, kad izveidojat jaunu mainīgo - to bieži sauc par mainīgā deklarēšanu - tās glabāšanai nepieciešama atmiņa. Tā kā jūsu dators ir mūsdienās, tajā var vienlaikus darbināt vairāk nekā vienu lietojumprogrammu, tāpēc katrai lietojumprogrammai ir jāpasaka jūsu OS (šeit Linux) ka tam nepieciešams tik daudz atmiņas. Kad rakstāt šāda veida kodu:

# iekļaut
# iekļaut
#define DISK_SPACE_ARRAY_LENGTH 7
void getFreeDiskSpace (int statsList [], size_t listLength)
atgriešanās;

int main ()
/ * Satur pēdējo 7 dienu brīvo vietu diskā. * /
int freeDiskSpace [DISK_SPACE_ARRAY_LENGTH] = 0;
getFreeDiskSpace (freeDiskSpace, DISK_SPACE_ARRAY_LENGTH);
atgriešanās EXIT_SUCCESS;

Masīvam freeDiskSpace ir nepieciešama atmiņa, tāpēc, lai iegūtu atmiņu, jums būs jālūdz Linux apstiprinājums. Tomēr, tā kā, lasot pirmkodu, ir acīmredzams, ka jums būs nepieciešams masīvs 7 int, kompilators to automātiski pieprasa Linux, un tas to piešķirs kaudzē. Tas būtībā nozīmē, ka šī krātuve tiek iznīcināta, kad atgriežat funkciju, kur mainīgais ir deklarēts. Tāpēc jūs to nevarat izdarīt:

# iekļaut
# iekļaut
#define DISK_SPACE_ARRAY_LENGTH 7
int * getFreeDiskSpace ()
int statsList [DISK_SPACE_ARRAY_LENGTH] = 0;
/ * KĀPĒC mēs to darām?! statsList tiks iznīcināts! * /
atgriešanās statistikaList;

int main ()
/ * Satur pēdējo 7 dienu brīvo vietu diskā. * /
int * freeDiskSpace = NULL;
freeDiskSpace = getFreeDiskSpace ();
atgriešanās EXIT_SUCCESS;

Jūs tagad vieglāk redzat problēmu? Tad jūs vēlaties savienot divas virknes. Programmā Python un JavaScript jūs rīkojieties šādi:

newStr = str1 + str2

Bet, kā jūs zināt, C valodā tas nedarbojas šādi. Tātad, lai izveidotu, piemēram, URL, jums jāsavieno divas virknes, piemēram, URL ceļš un domēna nosaukums. C, mēs esam strcat, labi, bet tas darbojas tikai tad, ja jums ir masīvs, kurā tam ir pietiekami daudz vietas.

Jums būs kārdinājums uzzināt jaunās virknes garumu, izmantojot strlen, un jums būs taisnība. Bet kā tad jūs lūgtu Linux rezervēt šo nezināmo atmiņas apjomu? Kompilators nevar jums palīdzēt: precīza vieta, kuru vēlaties piešķirt, ir zināma tikai izpildlaikā. Tas ir tieši tas, kur jums ir nepieciešams dinamisks sadalījums un malloc.

Rakstu savu pirmo C funkciju, izmantojot malloc

Pirms koda rakstīšanas, neliels paskaidrojums: malloc ļauj jums piešķirt noteiktu baitu skaitu lietojumprogrammas lietošanai. Lietošana ir patiešām vienkārša: jūs piezvanāt malloc ar nepieciešamo baitu skaitu, un tas atgriež rādītāju jaunajā apgabalā, kuru Linux rezervēja jums.

Jums ir tikai 3 pienākumi:

  1. Pārbaudiet, vai malloc atgriež NULL. Tas notiek, ja Linux nav pietiekami daudz atmiņas, lai nodrošinātu.
  2. Atbrīvojiet mainīgos pēc neizmantošanas. Pretējā gadījumā jūs iztērēsiet atmiņu, un tas palēninās jūsu lietojumprogrammu.
  3. Nekad nelietojiet atmiņas zonu pēc mainīgā atbrīvošanas.

Ja jūs ievērosiet visus šos noteikumus, viss notiks labi, un dinamiska piešķiršana jums atrisinās daudzas problēmas. Tā kā jūs izvēlaties, kad atbrīvojat atmiņu, varat droši atgriezt arī mainoc, kas piešķirts ar malloc. Vienkārši, neaizmirstiet to atbrīvot!

Ja jūs domājat, kā atbrīvot mainīgo, tas notiek ar bezmaksas funkciju. Zvaniet tam ar to pašu rādītāju, nekā malloc atgrieza jūs, un atmiņa ir atbrīvota.

Ļaujiet man jums parādīt īsu piemēru:

# iekļaut
# iekļaut
# iekļaut
/ *
* Zvanot uz šo funkciju, neaizmirstiet pārbaudīt, vai atgriešanās vērtība ir NULL
* Ja tas nav NULL, jums ir jāzvana bez maksas uz atgriezto rādītāju, kad vērtība ir sasniegta
* vairs netiek izmantots.
* /
char * getUrl (const char * const baseUrl, const char * const toolPath)
size_t finalUrlLen = 0;
char * finalUrl = NULL;
/ * Drošības pārbaude. * /
ja (baseUrl == NULL || toolPath == NULL)
atgriešanās NULL;

finalUrlLen = strlen (baseUrl) + strlen (toolPath);
/ * Neaizmirstiet “\ 0”, tāpēc + 1. * /
finalUrl = malloc (sizeof (char) * (finalUrlLen + 1));
/ * Ievērojot malloc noteikumus ... * /
ja (finalUrl == NULL)
atgriešanās NULL;

strcpy (finalUrl, baseUrl);
strcat (finalUrl, toolPath);
atgriešanās finalUrl;

int main ()
char * googleImages = NULL;
googleImages = getUrl ("https: // www.google.com "," / imghp ");
ja (googleImages == NULL)
atgriešanās EXIT_FAILURE;

liek ("Rīka URL:");
liek (googleImages);
/ * Tas vairs nav vajadzīgs, atbrīvojiet to. * /
bezmaksas (googleImages);
googleImages = NULL;
atgriešanās EXIT_SUCCESS;

Tātad jūs redzat praktisku piemēru dinamisko piešķīrumu izmantošanai. Pirmkārt, es izvairos no tādām kļūmēm kā, piemēram, getUrl atgriešanās vērtības piešķiršana tieši funkcijai. Tad es arī veltu laiku komentāriem un dokumentiem par to, ka atgriešanās vērtība ir pareizi jāatbrīvo. Es arī visur pārbaudu NULL vērtības, lai visu negaidīto varētu droši noķert, nevis avarēt lietojumprogrammu.

Visbeidzot, es īpaši rūpējos par mainīgā atbrīvošanu un pēc tam rādītāja iestatīšanu uz NULL. Tas ļauj izvairīties no kārdinājuma izmantot - pat kļūdas dēļ - tagad atbrīvoto atmiņas zonu. Bet, kā redzat, mainīgo ir viegli atbrīvot.

Jūs varat pamanīt, ka es malloc lietoju sizeof. Tas ļauj uzzināt, cik baitu char lieto, un precizē koda nolūku, lai tas būtu vieglāk lasāms. Attiecībā uz char, sizeof (char) vienmēr ir vienāds ar 1, bet, ja tā vietā izmantojat masīvu int, tas darbojas tieši tāpat. Piemēram, ja jums ir nepieciešams rezervēt 45 vid., Vienkārši rīkojieties šādi:

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

Tādā veidā jūs ātri redzat, cik daudz vēlaties piešķirt, tāpēc es vienmēr iesaku to izmantot.

Kā darbojas malloc zem pārsega?

malloc un free faktiski ir funkcijas, kas iekļautas visās C programmās, kas runās ar Linux jūsu vārdā. Tas arī atvieglos dinamisko piešķiršanu, jo sākumā Linux neļauj jums piešķirt visu lielumu mainīgos.

Linux nodrošina divus veidus, kā faktiski iegūt vairāk atmiņas: sbrk un mmap. Abiem ir ierobežojumi, un viens no tiem ir: jūs varat piešķirt tikai salīdzinoši lielas summas, piemēram, 4096 baitus vai 8 192 baitus. Jūs nevarat pieprasīt 50 baitus, kā es to darīju piemērā, bet jūs nevarat pieprasīt arī 5894 baitus.

Tam ir izskaidrojums: Linux ir jāsaglabā tabula, kurā norādīts, kura lietojumprogramma ir rezervējusi kādu atmiņas zonu. Šī tabula izmanto arī vietu, tādēļ, ja katram baitam šajā tabulā būtu nepieciešama jauna rinda, būtu nepieciešama liela atmiņas daļa. Tāpēc atmiņa tiek sadalīta lielos blokos, piemēram, 4096 baiti, un līdzīgi kā jūs nevarat nopirkt 2 ar pusi apelsīnus pārtikas preču veikalā, jūs nevarat prasīt pus blokus.

Tātad malloc paņems šos lielos blokus un jums iedos nelielu šķēli no šiem atmiņas blokiem, kad vien to piezvanīsit. Kā arī, ja jūs atbrīvojāt dažus mainīgos, bet nepietiek, lai attaisnotu visa bloka atbrīvošanu, malloc sistēma var saglabāt blokus un pārstrādāt atmiņas zonas, kad atkal piezvanāt malloc. Šī priekšrocība ir padarīt malloc ātrāku, tomēr malloc rezervēto atmiņu nevar izmantot nevienā citā lietojumprogrammā, savukārt programma to pašlaik neizmanto patiesībā.

Bet malloc ir gudrs: ja jūs piezvanīsit malloc, lai piešķirtu 16 MiB vai lielu summu, malloc, iespējams, lūgs Linux pilnus blokus, kas paredzēti tikai šim lielajam mainīgajam, izmantojot mmap. Tādā veidā, zvanot bez maksas, tas, visticamāk, ļaus izvairīties no vietas izšķiešanas. Neuztraucieties, malloc pārstrādē strādā daudz labāk nekā cilvēki ar mūsu atkritumiem!

Secinājums

Es domāju, ka tagad jūs labāk saprotat, kā tas viss darbojas. Protams, dinamiska piešķiršana ir liela tēma, un es domāju, ka mēs varam uzrakstīt pilnu grāmatu par šo tēmu, taču šim rakstam vajadzētu padarīt jūs apmierinātu gan ar jēdzienu, gan ar praktiskiem programmēšanas padomiem.

5 labākās arkādes spēles Linux
Mūsdienās datori ir nopietnas mašīnas, kuras izmanto spēlēšanai. Ja jūs nevarat iegūt jauno augsto rezultātu, jūs zināt, ko es domāju. Šajā ierakstā j...
Cīņa par Vesnotu 1.13.6 Izlaista attīstība
Cīņa par Vesnotu 1.13.6 izlaists pagājušajā mēnesī, ir sestais izstrādes izlaidums 1.13.x sērija un tā nodrošina vairākus uzlabojumus, īpaši lietotāja...
Kā instalēt League of Legends operētājsistēmā Ubuntu 14.04
Ja jūs esat League of Legends fans, tad šī ir iespēja jums izmēģināt League of Legends. Ņemiet vērā, ka LOL tiek atbalstīts PlayOnLinux, ja esat Linux...