Dynaaminen muistin allokointi C:ssä: malloc(), calloc()

⚡ Älykäs yhteenveto

C-kielen dynaaminen muistin allokointi varaa ja vapauttaa kekomuistia ajonaikana käyttämällä stdlib.h-kirjaston malloc()-, calloc()-, realloc()- ja free()-funktioita, jolloin ohjelmat voivat muuttaa taulukoiden ja rakenteiden kokoa joustavasti, kun vaatimukset ovat tuntemattomia ennen suoritusta.

  • 🧠 Pino vs. keko: Perusmuuttujat käyttävät automaattista pinomuistia, kun taas dynaaminen muisti sijaitsee keossa ja sitä hallitaan manuaalisesti osoittimien avulla.
  • 📦 malloc(): Varaa yhden pyydetyn tavukoon kokoisen alustamattoman lohkon ja palauttaa tyhjän osoittimen tai NULL-arvon, kun muistia ei ole riittävästi.
  • 🔢 calloc (): Varaa useita lohkoja taulukoille, asettaa jokaisen tavun nollaksi ja palauttaa osoittimen ensimmäiseen lohkoon.
  • 🔄 realloc(): Muuttaa olemassa olevan lohkon kokoa ylös- tai alaspäin säilyttäen samalla alkuperäisen sisällön mahdollisessa uudessa sijainnissa.
  • 🧹 vapaa(): Palauttaa muistia kekoon; jokainen malloc() tai calloc() tarvitsee vastaavan free()-funktion vuotojen estämiseksi.
  • 🤖 Tekoälyn apu: Tekoälyavustajat ja GitHub Copilot luonnostavat allokointikoodia ja merkitsevät puuttuvia free()-kutsuja ja vuotoja.

Dynaaminen muistin varaus C:ssä

Kuinka C-muistinhallinta toimii?

Kun määrittelet muuttujan käyttämällä perustietotyyppiä, C-kääntäjä varaa muuttujalle automaattisesti muistitilaa muistipoolista, jota kutsutaan pinoksi.

Esimerkiksi liukulukumuuttuja vie tyypillisesti 4 tavua (alustan mukaan) kun se deklaroidaan. Voimme tarkistaa tämän tiedon käyttämällä sizeof-operaattoria alla olevan esimerkin mukaisesti.

#include <stdio.h>
int main() { float x; printf("The size of float is %d bytes", sizeof(x)); return 0;}

Tuotos on:

 The size of float is 4 bytes

Lisäksi määritetyn kokoinen matriisi on allokoitu vierekkäisiin muistilohkoihin, jokaisella lohkolla on yhden elementin koko:

#include <stdio.h>
int main() { float arr[10];
printf("The size of the float array with 10 element is %d", sizeof(arr)); return 0;}

Tulos on:

 The size of the float array with 10 element is 40

Kuten tähän mennessä on opittu, perustietotyypin tai taulukon määrittelyssä muistia hallitaan automaattisesti. C-kielessä on kuitenkin muistin allokointiprosessi, jonka avulla voit toteuttaa ohjelman, jossa taulukon koko on epävarma ennen ohjelman suorittamista (ajonaikainen). Tätä prosessia kutsutaan dynaamiseksi muistin allokoinniksi.

Dynaaminen muistin varaus C:ssä

Dynaaminen muistin allokointi on muistin manuaalista allokointia ja vapauttamista ohjelmointitarpeidesi mukaan. Dynaamista muistia hallitaan ja tarjoillaan osoittimilla, jotka osoittavat juuri allokoituun muistitilaan alueella, jota kutsumme keoksi.

Nyt voit luoda ja tuhota joukon elementtejä dynaamisesti ajon aikana ilman ongelmia. Yhteenvetona voidaan todeta, että automaattinen muistinhallinta käyttää pinoa ja C Dynamic Memory Allocation käyttää pinoa.

The kirjastossa on dynaamisesta muistinhallinnasta vastaavat toiminnot.

Toiminto Tarkoitus
malloc () Varaa pyydetyn koon muistin ja palauttaa osoittimen ensimmäiseen tavuun
varattu tila.
calloc() Varaa tilaa taulukon elementeille. Alustaa elementit nollaan ja palauttaa osoittimen muistiin.
realloc() Sitä käytetään muuttamaan aiemmin varatun muistitilan kokoa.
Vapaa() Vapauttaa tai tyhjentää aiemmin varatun muistitilan.

Keskustellaan yllä olevista toiminnoista niiden sovelluksen kanssa

malloc()-funktio C:ssä

Funktio C malloc() tarkoittaa muistin varausta. Se on toiminto, jota käytetään varaamaan muistilohko dynaamisesti. Se varaa määritetyn kokoisen muistitilan ja palauttaa muistipaikkaan osoittavan nollaosoittimen. Palautettu osoitin on yleensä tyyppiä void. Se tarkoittaa, että voimme määrittää C malloc() -funktion mille tahansa osoittimelle.

Malloc()-funktion syntaksi:

ptr = (cast_type *) malloc (byte_size);

Täällä

  • ptr on cast_typen osoitin.
  • C malloc()-funktio palauttaa osoittimen varattuun muistiin byte_size.

Esimerkki malloc():

Example: ptr = (int *) malloc (50)

Kun tämä käsky on suoritettu onnistuneesti, varataan 50 tavun muistitilaa. Varatun tilan ensimmäisen tavun osoite on osoitettu osoittimelle ptr, jonka tyyppi on int.

Harkitse toista esimerkkiä:

#include <stdlib.h>
int main(){
int *ptr;
ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */
    if (ptr != NULL) {
      *(ptr + 5) = 480; /* assign 480 to sixth integer */
      printf("Value of the 6th integer is %d",*(ptr + 5));
    }
}

lähtö:

Value of the 6th integer is 480

C malloc()-funktio

  1. Huomaa, että sizeof(*ptr):ia käytettiin sizeof(int):in sijaan koodin vankemman toiminnan varmistamiseksi, kun *ptr-deklaraatio tyypitetään myöhemmin eri tietotyyppiin.
  2. Varaus voi epäonnistua, jos muisti ei riitä. Tässä tapauksessa se palauttaa NULL-osoittimen. Joten sinun tulee sisällyttää koodi tarkistaaksesi NULL-osoittimen.
  3. Muista, että varattu muisti on peräkkäinen ja sitä voidaan käsitellä taulukona. Voimme käyttää osoitinaritmetiikkaa taulukon elementtien käyttämiseen hakasulkeiden [ ] sijaan. Suosittelemme käyttämään + viittaamaan taulukon elementteihin, koska inkrementaatio ++ tai += muuttaa järjestelmän tallentamaa osoitetta. osoitin.

Malloc()-funktiota voidaan käyttää myös merkkitietotyypin sekä monimutkaisten tietotyyppien, kuten rakenteiden, kanssa.

free()-funktio C:ssä

Muisti varten muuttujat jaetaan automaattisesti käännöshetkellä. Dynaamisessa muistin allokoinnissa muisti on vapautettava eksplisiittisesti. Jos et tee sitä, saatat kohdata muistin loppumisesta virheen.

C-kielessä kutsutaan free()-funktiota muistin vapauttamiseen/vapauttamiseen. Vapauttamalla muistia ohjelmassasi saat enemmän muistia käyttöön myöhemmin.

Esimerkiksi:

#include <stdio.h>
int main() {
int* ptr = malloc(10 * sizeof(*ptr));
if (ptr != NULL){
  *(ptr + 2) = 50;
  printf("Value of the 2nd integer is %d",*(ptr + 2));
}
free(ptr);
}

lähtö:

 Value of the 2nd integer is 50

calloc()-funktio C:ssä

Funktio C calloc() tarkoittaa jatkuvaa allokaatiota. Tätä toimintoa käytetään useiden muistilohkojen varaamiseen. Se on dynaaminen muistin varaustoiminto, jota käytetään varaamaan muisti monimutkaisille tietorakenteille, kuten taulukoille ja rakenteille.

Malloc()-funktiota käytetään varaamaan yksi lohko muistitilaa, kun taas calloc()-funktiota C:ssä käytetään varaamaan useita muistitilalohkoja. Jokainen calloc()-funktion allokoima lohko on samankokoinen.

Calloc()-funktion syntaksi:

ptr = (cast_type *) calloc (n, size);

Yllä olevaa käskyä käytetään allokoimaan n samankokoista muistilohkoa.

Kun muistitila on varattu, kaikki tavut alustetaan nollaan.

Palautetaan osoitin, joka on tällä hetkellä varatun muistitilan ensimmäisessä tavussa.

Aina kun muistitilan varaamisessa tapahtuu virhe, kuten muistin puute, palautetaan nollaosoitin.

Esimerkki calloc():

Alla oleva ohjelma laskee aritmeettisen sekvenssin summan.

#include <stdio.h>
    int main() {
        int i, * ptr, sum = 0;
        ptr = calloc(10, sizeof(int));
        if (ptr == NULL) {
            printf("Error! memory not allocated.");
            exit(0);
        }
        printf("Building and calculating the sequence sum of the first 10 terms \ n ");
        for (i = 0; i < 10; ++i) { * (ptr + i) = i;
            sum += * (ptr + i);
        }
        printf("Sum = %d", sum);
        free(ptr);
        return 0;
    }

Tulos:

Building and calculating the sequence sum of the first 10 terms
Sum = 45

calloc() vs. malloc(): Keskeiset erot

Seuraavassa on keskeinen ero malloc() vs calloc() ryhmässä C:

Calloc()-funktio on yleensä sopivampi ja tehokkaampi kuin malloc()-funktio. Vaikka molempia toimintoja käytetään varaamaan muistitilaa, calloc() voi varata useita lohkoja kerralla. Sinun ei tarvitse pyytää muistilohkoa joka kerta. Calloc()-funktiota käytetään monimutkaisissa tietorakenteissa, jotka vaativat enemmän muistitilaa.

C:n calloc():n allokoima muistilohko alustetaan aina nollaan, kun taas C:n malloc()-funktiossa se sisältää aina roskaarvon.

realloc()-funktio C:ssä

C-kielen realloc()-funktion avulla voit lisätä jo varatun muistin kokoa. Se laajentaa nykyistä lohkoa jättäen alkuperäisen sisällön ennalleen. C-kielen realloc() tarkoittaa muistin uudelleenallokointia (reallokation of memory).

realloc()-funktiota voidaan käyttää myös pienentämään aiemmin varatun muistin kokoa.

Realloc()-funktion syntaksi:

ptr = realloc (ptr,newsize);

Yllä oleva käsky varaa uuden muistitilan, jonka koko on määritetty muuttujassa newsize. Toiminnon suorittamisen jälkeen osoitin palautetaan muistilohkon ensimmäiseen tavuun. Uusi koko voi olla suurempi tai pienempi kuin edellinen muisti. Emme voi olla varmoja siitä, osoittaako vasta varattu lohko samaan paikkaan kuin edellinen muistilohko. Tämä toiminto kopioi kaikki aiemmat tiedot uudelle alueelle. Se varmistaa, että tiedot pysyvät turvassa.

Esimerkki realloc():

#include <stdio.h>
int main () {
   char *ptr;
   ptr = (char *) malloc(10);
   strcpy(ptr, "Programming");
   printf(" %s,  Address = %u\n", ptr, ptr);

   ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size
   strcat(ptr, " In 'C'");
   printf(" %s,  Address = %u\n", ptr, ptr);
   free(ptr);
   return 0;
}

Aina kun C:n realloc() johtaa epäonnistuneeseen toimintoon, se palauttaa nollaosoittimen ja myös edellinen data vapautetaan.

Dynaamiset taulukot C:ssä

Dynaaminen matriisi C:ssä mahdollistaa elementtien määrän kasvamisen tarpeen mukaan. C Dynaamista taulukkoa käytetään laajalti tietojenkäsittelytieteen algoritmeissa.

Seuraavassa ohjelmassa olemme luoneet dynaamisen taulukon ja muuttaneet sen kokoa C

#include <stdio.h>
    int main() {
        int * arr_dynamic = NULL;
        int elements = 2, i;
        arr_dynamic = calloc(elements, sizeof(int)); //Array with 2 integer blocks
        for (i = 0; i < elements; i++) arr_dynamic[i] = i;
        for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]);
        elements = 4;
        arr_dynamic = realloc(arr_dynamic, elements * sizeof(int)); //reallocate 4 elements
        printf("After realloc\n");
        for (i = 2; i < elements; i++) arr_dynamic[i] = i;
        for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]);
        free(arr_dynamic);
    }

C Dynamic array -ohjelman tulos näytöllä:

 
arr_dynamic[0]=0
arr_dynamic[1]=1
After realloc
arr_dynamic[0]=0
arr_dynamic[1]=1
arr_dynamic[2]=2
arr_dynamic[3]=3

UKK

Muistivuoto tapahtuu, kun malloc():n tai calloc():n ottama kekomuisti ei koskaan vapautu. Estä se yhdistämällä jokainen allokointi vastaavaan free()-kutsuun, kun lohkoa ei enää tarvita.

Roikkuva osoitin sisältää edelleen free()-funktion jo vapauttaman muistin osoitteen. Sen poisviittaus aiheuttaa määrittelemätöntä toimintaa, joten aseta osoittimelle NULL heti vapauttamisen jälkeen turvallisuuden takaamiseksi.

Ei. C:ssä ei ole roskankerääjää, joten kekomuistia ei koskaan vapauteta automaattisesti. Ohjelmoijan on vapautettava jokainen lohko eksplisiittisesti free()-funktiolla; muuten allokointi jatkuu, kunnes ohjelma päättyy.

Ei. Free()-funktion kutsuminen kahdesti samassa osoitteessa on kaksinkertainen free-kutsu ja laukaisee määrittelemättömän toiminnan tai kaatumiset. Osoittimen asettaminen arvoon NULL ensimmäisen free()-funktion jälkeen tekee myöhemmistä free()-funktioista vaarattomia.

realloc(NULL, size) toimii täsmälleen kuten malloc(size) ja varaa uuden lohkon. realloc(ptr, 0) vapauttaa lohkon, joten kaappaa aina palautettu osoitin alkuperäisen päällekirjoittamisen sijaan.

Työkaluja, kuten Valgrind, AddressSanitizer ja Dr. Memory track kaikki vapautetut allokointi- ja raporttilohkot sekä tarkka rivi, helping paikannat vuodot ennen vapautusta.

Kyllä. Tekoälykoodausassistentti luonnostelee malloc()-, calloc()- ja free()-sekvenssit kehotteesta, selittää osoitinvirheet ja merkitsee puuttuvat free()-kutsuja. Käännä ja testaa aina luotu koodi ennen kuin luotat siihen.

GitHub Copilot ehdottaa allokointilohkoja, NULL-tarkistuksia ja free()-kutsujen yhteensopivuutta kommentin perusteella; tarkista jokainen täydennys vuotojen ja oikeiden kokojen varalta ennen lähettämistä.

Tiivistä tämä viesti seuraavasti: