Dynamisk minneallokering i C: malloc(), calloc()

⚡ Smart oppsummering

Dynamisk minneallokering i C reserverer og frigjør heap-minne under kjøretid ved hjelp av funksjonene malloc(), calloc(), realloc() og free() fra stdlib.h-biblioteket, slik at programmer kan justere størrelsen på arrayer og strukturer fleksibelt når kravene er ukjente før utførelse.

  • 🧠 Stabel vs. haug: Grunnleggende variabler bruker den automatiske stakken, mens dynamisk minne ligger på heapen og administreres manuelt gjennom pekere.
  • 📦 malloc(): Reserverer én uinitialisert blokk med en forespurt bytestørrelse og returnerer en void-peker, eller NULL når minnet er utilstrekkelig.
  • 🔢 calloc(): Tildeler flere blokker for arrayer, setter hver byte til null og returnerer en peker til den første blokken.
  • 🔄 realloc(): Endrer størrelsen på en eksisterende blokk opp eller ned samtidig som det opprinnelige innholdet bevares på en mulig ny plassering.
  • 🧹 gratis(): Returnerer minne til heapen; hver malloc() eller calloc() trenger en matchende free() for å forhindre lekkasjer.
  • 🤖 AI-hjelp: AI-assistenter og GitHub Copilot utkaster tildelingskode og flagger manglende free()-kall og lekkasjer.

Dynamisk minnetildeling i C

Hvordan fungerer minnebehandling i C?

Når du deklarerer en variabel ved hjelp av en grunnleggende datatype, tildeler C-kompilatoren automatisk minneplass for variabelen i et minnebasseng kalt stakken.

For eksempel tar en flyttallsvariabel vanligvis 4 byte (avhengig av plattformen) når den deklareres. Vi kan bekrefte denne informasjonen ved å bruke sizeof-operatoren som vist i eksemplet nedenfor.

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

Utgangen vil være:

 The size of float is 4 bytes

Dessuten er en matrise med en spesifisert størrelse tildelt i sammenhengende minneblokker, hver blokk har størrelsen for ett 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;}

Resultatet er:

 The size of the float array with 10 element is 40

Som vi har lært så langt, administreres minnet automatisk når man deklarerer en grunnleggende datatype eller en array. Det finnes imidlertid en prosess for å allokere minne i C som lar deg implementere et program der arraystørrelsen er ubestemt før du kjører programmet (kjøretidsmodus). Denne prosessen kalles «dynamisk minneallokering».

Dynamisk minnetildeling i C

Dynamisk minneallokering er manuell tildeling og frigjøring av minne i henhold til programmeringsbehovene dine. Dynamisk minne administreres og betjenes med pekere som peker til den nylig tildelte minneplassen i et område som vi kaller heapen.

Nå kan du opprette og ødelegge en rekke elementer dynamisk under kjøring uten problemer. For å oppsummere bruker den automatiske minneadministrasjonen stabelen, og C Dynamic Memory Allocation bruker heapen.

De biblioteket har funksjoner som er ansvarlige for Dynamic Memory Management.

Funksjon Formål
malloc () Tildeler minnet med ønsket størrelse og returnerer pekeren til den første byten av
tildelt plass.
calloc() Tildeler plass for elementer i en matrise. Initialiserer elementene til null og returnerer en peker til minnet.
realloc() Den brukes til å endre størrelsen på tidligere tildelt minneplass.
Gratis() Frigjør eller tømmer tidligere tildelt minneplass.

La oss diskutere funksjonene ovenfor med applikasjonen deres

malloc()-funksjonen i C

C malloc()-funksjonen står for minneallokering. Det er en funksjon som brukes til å tildele en minneblokk dynamisk. Den reserverer minneplass av spesifisert størrelse og returnerer null-pekeren som peker til minneplasseringen. Pekeren som returneres er vanligvis av typen void. Det betyr at vi kan tilordne C malloc()-funksjonen til enhver peker.

Syntaks for malloc() funksjon:

ptr = (cast_type *) malloc (byte_size);

Her

  • ptr er en peker av cast_type.
  • C malloc()-funksjonen returnerer en peker til det tildelte minnet til byte_size.

Eksempel på malloc():

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

Når denne setningen er utført, er en minneplass på 50 byte reservert. Adressen til den første byten med reservert plass er tilordnet pekeren ptr av typen int.

Tenk på et annet eksempel:

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

Utgang:

Value of the 6th integer is 480

C malloc() funksjon

  1. Legg merke til at sizeof(*ptr) ble brukt i stedet for sizeof(int) for å gjøre koden mer robust når *ptr-deklarasjonen senere typecastes til en annen datatype.
  2. Tildelingen kan mislykkes hvis minnet ikke er tilstrekkelig. I dette tilfellet returnerer den en NULL-peker. Så du bør inkludere kode for å se etter en NULL-peker.
  3. Husk at det tildelte minnet er sammenhengende, og det kan behandles som en matrise. Vi kan bruke pekeraritmetikk for å få tilgang til matriseelementene i stedet for å bruke parenteser [ ]. Vi anbefaler å bruke + for å referere til matriseelementer fordi bruk av inkrementering ++ eller += endrer adressen lagret av pekeren.

Malloc()-funksjonen kan også brukes med karakterdatatypen så vel som komplekse datatyper som strukturer.

free() funksjon i C

Minnet for variabler blir automatisk deallokert på kompileringstidspunktet. Ved dynamisk minneallokering må du tildele minne eksplisitt. Hvis det ikke er gjort, kan det oppstå en feil for tomt for minne.

Free()-funksjonen kalles for å frigjøre/avallokere minne i C. Ved å frigjøre minne i programmet ditt, gjør du mer tilgjengelig for senere bruk.

For eksempel:

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

Utgang:

 Value of the 2nd integer is 50

calloc() funksjon i C

C calloc()-funksjonen står for sammenhengende allokering. Denne funksjonen brukes til å tildele flere minneblokker. Det er en dynamisk minneallokeringsfunksjon som brukes til å allokere minnet til komplekse datastrukturer som matriser og strukturer.

Malloc()-funksjonen brukes til å tildele en enkelt blokk med minneplass mens calloc() i C brukes til å tildele flere blokker med minneplass. Hver blokk som tildeles av calloc()-funksjonen er av samme størrelse.

Syntaks for calloc() funksjon:

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

Utsagnet ovenfor brukes til å tildele n minneblokker av samme størrelse.

Etter at minneplassen er tildelt, initialiseres alle byte til null.

Pekeren som for øyeblikket befinner seg ved den første byte av den tildelte minneplassen returneres.

Hver gang det er en feil ved tildeling av minneplass, for eksempel mangel på minne, returneres en null-peker.

Eksempel på calloc():

Programmet nedenfor beregner summen av en aritmetisk sekvens.

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

Resultat:

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

calloc() vs. malloc(): Nøkkelforskjeller

Følgende er nøkkelforskjellen mellom malloc() kontra calloc() i C:

Calloc()-funksjonen er generelt mer egnet og effektiv enn malloc()-funksjonen. Mens begge funksjonene brukes til å tildele minneplass, kan calloc() tildele flere blokker på en gang. Du trenger ikke be om en minneblokk hver gang. Calloc()-funksjonen brukes i komplekse datastrukturer som krever større minneplass.

Minneblokken tildelt av en calloc() i C initialiseres alltid til null, mens den i funksjon malloc() i C alltid inneholder en søppelverdi.

realloc()-funksjonen i C

Ved å bruke realloc()-funksjonen i C kan du legge til mer minnestørrelse til allerede allokert minne. Den utvider den gjeldende blokken mens det opprinnelige innholdet forblir som det er. realloc() i C står for reallokering av minne.

realloc() kan også brukes til å redusere størrelsen på det tidligere tildelte minnet.

Syntaks for realloc() funksjon:

ptr = realloc (ptr,newsize);

Utsagnet ovenfor tildeler en ny minneplass med en spesifisert størrelse i variabelen nyhetsstørrelse. Etter å ha utført funksjonen, vil pekeren bli returnert til den første byten i minneblokken. Den nye størrelsen kan være større eller mindre enn det forrige minnet. Vi kan ikke være sikre på at hvis den nylig tildelte blokken vil peke til samme plassering som den forrige minneblokken. Denne funksjonen vil kopiere alle tidligere data i den nye regionen. Det sørger for at data forblir trygge.

Eksempel på 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;
}

Hver gang realloc() i C resulterer i en mislykket operasjon, returnerer den en null-peker, og tidligere data frigjøres også.

Dynamiske matriser i C

En dynamisk array i C lar antallet elementer vokse etter behov. C Dynamic array er mye brukt i datavitenskapelige algoritmer.

I det følgende programmet har vi opprettet og endret størrelsen på en dynamisk matrise i 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);
    }

Resultat av C Dynamic array-program på skjermen:

 
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

Spørsmål og svar

En minnelekkasje oppstår når heap-minne tatt av malloc() eller calloc() aldri frigjøres. Forebygg dette ved å koble hver allokering med et matchende free()-kall når blokken ikke lenger er nødvendig.

En dinglende peker inneholder fortsatt adressen til minnet som free() allerede har frigitt. Dereferanse til den forårsaker udefinert oppførsel, så tilordne NULL til pekeren umiddelbart etter frigjøring for å være på den sikre siden.

Nei. C har ingen søppelinnsamler, så heap-minne blir aldri gjenvunnet automatisk. Programmereren må frigi hver blokk eksplisitt med free(); ellers vedvarer allokeringen til programmet avsluttes.

Nei. Å kalle free() to ganger på én adresse er en dobbel free og utløser udefinert oppførsel eller krasj. Å sette pekeren til NULL etter den første free() gjør senere free() ufarlige.

realloc(NULL, size) fungerer akkurat som malloc(size) og allokerer en ny blokk. realloc(ptr, 0) frigjør blokken, så fang alltid den returnerte pekeren i stedet for å overskrive den opprinnelige.

Verktøy som Valgrind, AddressSanitizer og Dr. Memory track alle allokerings- og rapportblokker som aldri ble frigjort, sammen med den nøyaktige linjen, helping du finner lekkasjer før utslipp.

Ja. En AI-kodingsassistent utarbeider malloc(), calloc() og free()-sekvenser fra en ledetekst, forklarer pekerfeil og flagger manglende free()-kall. Kompiler og test alltid den genererte koden før du stoler på den.

GitHub Copilot foreslår allokeringsblokker, NULL-sjekker og matchende free()-kall fra en kommentar; gjennomgå hver fullføring for lekkasjer og riktige størrelser før du sender den.

Oppsummer dette innlegget med: