Dinamička alokacija memorije u C-u: malloc(), calloc()

⚡ Pametni sažetak

Dinamička alokacija memorije u C-u rezervira i oslobađa heap memoriju tijekom izvođenja pomoću funkcija malloc(), calloc(), realloc() i free() iz biblioteke stdlib.h, omogućujući programima fleksibilno dimenzioniranje nizova i struktura kada su zahtjevi nepoznati prije izvršavanja.

  • 🧠 Stog vs. hrpa: Osnovne varijable koriste automatski stog, dok se dinamička memorija nalazi na hrpi i njome se upravlja ručno putem pokazivača.
  • ???? malloc(): Rezervira jedan neinicijalizirani blok tražene veličine bajta i vraća pokazivač void ili NULL kada nema dovoljno memorije.
  • 🔢 calloc(): Dodjeljuje više blokova za nizove, postavlja svaki bajt na nulu i vraća pokazivač na prvi blok.
  • 🔄 realoc(): Mijenja veličinu postojećeg bloka prema gore ili dolje, a istovremeno čuva izvorni sadržaj na potencijalno novoj lokaciji.
  • 🧹 besplatno(): Vraća memoriju na hrpu; svaki malloc() ili calloc() treba odgovarajući free() kako bi se spriječilo curenje.
  • 🤖 Pomoć umjetne inteligencije: AI asistenti i GitHub Copilot izrađuju kod za alokaciju i označavaju nedostajuće free() pozive i curenja.

Dinamička dodjela memorije u C

Kako funkcionira upravljanje memorijom u C-u?

Kada deklarirate varijablu koristeći osnovni tip podataka, C kompajler automatski dodjeljuje memorijski prostor za varijablu u memorijskom skupu koji se naziva stog.

Na primjer, varijabla s float brojem obično zauzima 4 bajta (ovisno o platformi) kada se deklarira. Ove informacije možemo provjeriti pomoću operatora sizeof kao što je prikazano u donjem primjeru.

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

Izlaz će biti:

 The size of float is 4 bytes

Također, polje s određenom veličinom alocirano je u susjednim blokovima memorije, svaki blok ima veličinu za jedan element:

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

Rezultat je:

 The size of the float array with 10 element is 40

Kao što je do sada naučeno, prilikom deklariranja osnovnog tipa podataka ili niza, memorija se automatski upravlja. Međutim, postoji proces za alokaciju memorije u C-u koji će vam omogućiti implementaciju programa u kojem je veličina niza neodređena dok ne pokrenete program (runtime). Taj se proces naziva "Dinamička alokacija memorije".

Dinamička dodjela memorije u C

Dinamička alokacija memorije je ručna alokacija i oslobađanje memorije prema vašim programskim potrebama. Dinamičkom memorijom se upravlja i poslužuje pokazivači koji pokazuju na novododijeljeni memorijski prostor u području koje nazivamo hrpom (heap).

Sada možete stvarati i uništavati niz elemenata dinamički tijekom izvođenja bez ikakvih problema. Ukratko, automatsko upravljanje memorijom koristi stog, a C dinamička dodjela memorije koristi hrpu.

The biblioteka ima funkcije odgovorne za dinamičko upravljanje memorijom.

funkcija Svrha
malloc () Dodjeljuje memoriju tražene veličine i vraća pokazivač na prvi bajt od
dodijeljeni prostor.
calloc() Dodjeljuje prostor za elemente niza. Inicijalizira elemente na nulu i vraća pokazivač u memoriju.
realloc() Koristi se za promjenu veličine prethodno dodijeljenog memorijskog prostora.
Besplatno() Oslobađa ili prazni prethodno dodijeljeni memorijski prostor.

Razmotrimo gore navedene funkcije s njihovom primjenom

funkcija malloc() u C-u

Funkcija C malloc() označava dodjelu memorije. To je funkcija koja se koristi za dinamičku dodjelu bloka memorije. Rezervira memorijski prostor određene veličine i vraća nulti pokazivač koji pokazuje na memorijsku lokaciju. Vraćeni pokazivač obično je tipa void. To znači da C malloc() funkciju možemo dodijeliti bilo kojem pokazivaču.

Sintaksa funkcije malloc():

ptr = (cast_type *) malloc (byte_size);

Ovdje,

  • ptr je pokazivač na cast_type.
  • Funkcija C malloc() vraća pokazivač na dodijeljenu memoriju byte_size.

Primjer malloc():

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

Kada se ova izjava uspješno izvrši, rezervira se memorijski prostor od 50 bajtova. Adresa prvog bajta rezerviranog prostora dodjeljuje se pokazivaču ptr tipa int.

Razmotrite još jedan primjer:

#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));
    }
}

Izlaz:

Value of the 6th integer is 480

C malloc() funkcija

  1. Primijetite da je korištena sizeof(*ptr) umjesto sizeof(int) kako bi kod bio robusniji kada se deklaracija *ptr kasnije pretvori u drugi tip podataka.
  2. Dodjeljivanje možda neće uspjeti ako memorija nije dovoljna. U ovom slučaju, vraća NULL pokazivač. Dakle, trebali biste uključiti kod za provjeru pokazivača NULL.
  3. Imajte na umu da je dodijeljena memorija kontinuirana i da se može tretirati kao niz. Možemo koristiti aritmetiku pokazivača za pristup elementima niza umjesto korištenja zagrada []. Savjetujemo da koristite + za pozivanje na elemente polja jer korištenje inkrementacije ++ ili += mijenja adresu pohranjenu od strane pokazivač.

Funkcija Malloc() također se može koristiti sa karakternim tipom podataka, kao i sa složenim tipovima podataka kao što su strukture.

funkcija free() u C-u

Uspomena za varijable automatski se poništava tijekom kompilacije. U dinamičkoj dodjeli memorije morate eksplicitno osloboditi memoriju. Ako to ne učinite, mogli biste naići na pogrešku nedostatka memorije.

Funkcija free() poziva se za oslobađanje/dealociranje memorije u C-u. Oslobađanjem memorije u vašem programu, činite više memorije dostupnom za kasniju upotrebu.

Na primjer:

#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);
}

Izlaz:

 Value of the 2nd integer is 50

funkcija calloc() u C-u

Funkcija C calloc() označava kontinuiranu dodjelu. Ova se funkcija koristi za dodjelu više blokova memorije. To je funkcija dinamičke dodjele memorije koja se koristi za dodjelu memorije složenim podatkovnim strukturama kao što su nizovi i strukture.

Funkcija Malloc() koristi se za dodjelu jednog bloka memorijskog prostora, dok se calloc() u C-u koristi za dodjelu više blokova memorijskog prostora. Svaki blok dodijeljen funkcijom calloc() iste je veličine.

Sintaksa funkcije calloc():

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

Gornja izjava koristi se za dodjelu n memorijskih blokova iste veličine.

Nakon što je memorijski prostor dodijeljen, svi bajtovi se inicijaliziraju na nulu.

Vraća se pokazivač koji je trenutno na prvom bajtu dodijeljenog memorijskog prostora.

Kad god postoji pogreška pri dodjeli memorijskog prostora, kao što je nedostatak memorije, tada se vraća nulti pokazivač.

Primjer calloc():

Program u nastavku izračunava zbroj aritmetičkog niza.

#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;
    }

Rezultat:

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

calloc() u odnosu na malloc(): Ključne razlike

Slijedi ključna razlika između malloc() u odnosu na calloc() u C:

Funkcija calloc() općenito je prikladnija i učinkovitija od funkcije malloc(). Dok se obje funkcije koriste za dodjelu memorijskog prostora, calloc() može dodijeliti više blokova odjednom. Ne morate svaki put zahtijevati memorijski blok. Funkcija calloc() koristi se u složenim podatkovnim strukturama koje zahtijevaju veći memorijski prostor.

Memorijski blok koji dodjeljuje calloc() u C-u uvijek se inicijalizira na nulu, dok u funkciji malloc() u C-u uvijek sadrži vrijednost smeća.

funkcija realloc() u C-u

Pomoću funkcije realloc() u jeziku C možete dodati već dodijeljenu memoriju. Ona proširuje trenutni blok, a izvorni sadržaj ostavlja netaknut. realloc() u jeziku C znači realokacija memorije.

realloc() se također može koristiti za smanjenje veličine prethodno dodijeljene memorije.

Sintaksa funkcije realloc():

ptr = realloc (ptr,newsize);

Gornja izjava dodjeljuje novi memorijski prostor s određenom veličinom u varijabli newsize. Nakon izvršenja funkcije, pokazivač će se vratiti na prvi bajt memorijskog bloka. Nova veličina može biti veća ili manja od prethodne memorije. Ne možemo biti sigurni hoće li novododijeljeni blok pokazivati ​​na istu lokaciju kao prethodni memorijski blok. Ova funkcija će kopirati sve prethodne podatke u novu regiju. Osigurava da će podaci ostati sigurni.

Primjer 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;
}

Kad god realloc() u C rezultira neuspješnom operacijom, vraća nulti pokazivač, a prethodni podaci se također oslobađaju.

Dinamički nizovi u C

Dinamičko polje u C-u omogućuje povećanje broja elemenata prema potrebi. C Dinamički niz naširoko se koristi u algoritmima računalne znanosti.

U sljedećem programu stvorili smo i promijenili veličinu dinamičkog niza 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);
    }

Rezultat programa C Dynamic array na ekranu:

 
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

Pitanja i odgovori

Do curenja memorije dolazi kada se memorija koju zauzmu funkcije malloc() ili calloc() nikada ne oslobodi. Spriječite to uparivanjem svake alokacije s odgovarajućim pozivom funkcije free() nakon što blok više nije potreban.

Viseći pokazivač i dalje sadrži adresu memorije koju je free() već oslobodio. Dereferenciranje uzrokuje nedefinirano ponašanje, stoga pokazivaču odmah nakon oslobađanja dodijelite NULL radi sigurnosti.

Ne. C nema sakupljač smeća, pa se memorija heap-a nikada ne oslobađa automatski. Programer mora eksplicitno osloboditi svaki blok pomoću free(); inače se alokacija nastavlja sve dok se program ne završi.

Ne. Pozivanje free() dva puta na istoj adresi je dvostruko oslobađanje i pokreće nedefinirano ponašanje ili rušenje. Postavljanje pokazivača na NULL nakon prvog free() čini svaki kasniji free() bezopasnim.

realloc(NULL, size) se ponaša potpuno isto kao malloc(size) i dodjeljuje novi blok. realloc(ptr, 0) oslobađa blok, stoga uvijek uhvatite vraćeni pokazivač umjesto da prepišete preko izvornog.

Alati kao što su Valgrind, AddressSanitizer i Dr. Memory track svaku alokaciju i prijavi blokove koji nikada nisu oslobođeni, zajedno s točnom linijom, helping locirate curenja prije puštanja.

Da. Pomoćnik za kodiranje umjetne inteligencije iz prompta izrađuje nizove malloc(), calloc() i free(), objašnjava pogreške pokazivača i označava nedostajuće pozive free(). Uvijek kompajlirajte i testirajte generirani kod prije nego što mu vjerujete.

GitHub kopilot predlaže alokacijske blokove, NULL provjere i odgovarajuće free() pozive iz komentara; pregledajte svako dovršavanje radi propuštanja i ispravnih veličina prije nego što ga pošaljete.

Sažmite ovu objavu uz: