malloc() Funktion i C-bibliotek med EXEMPEL

⚡ Smart sammanfattning

malloc() i C reserverar ett minnesblock på heapen vid körning och returnerar en void-pekare till sin första byte, vilket låter program begära lagring vars storlek är okänd tills koden faktiskt exekveras.

  • 🧠 Körtidsallokering: malloc() reserverar minne under körning när den erforderliga storleken inte är känd vid kompileringstillfället.
  • 📦 Syntax: En cast_type-pekare tar emot malloc(byte_size), vanligtvis dimensionerad med sizeof för portabilitet.
  • ⚠️ NULL-kontroll: En misslyckad begäran returnerar en NULL-pekare, så validera resultatet innan du avreferenserar det.
  • Pekararitmetik: Blocket är sammanhängande, så använd + istället för ++ för att nå arrayelement.
  • 🧹 Frigör minnet: Släpp varje block med free() för att förhindra minnesläckor och dinglande pekare.
  • 🤖 AI-hjälp: AI-assistenter och GitHub Copilot utarbetar malloc()-anrop och flaggar saknade free()-satser.

malloc()-funktionen i C

Vad är malloc i C?

Funktionen malloc() står för minnesallokering. Det är en funktion som används för att tilldela ett minnesblock dynamiskt. Den reserverar minnesutrymme av specificerad storlek och returnerar nollpekaren som pekar till minnesplatsen. Pekaren som returneras är vanligtvis av typen void. Det betyder att vi kan tilldela malloc-funktion till vilken pekare som helst.

Vad är malloc i C

syntax

ptr = (cast_type *) malloc (byte_size);

Här,

  • ptr är en pekare av cast_type.
  • Malloc-funktionen returnerar en pekare till det tilldelade minnet av byte_size.
Example: ptr = (int *) malloc (50)

När denna sats exekveras framgångsrikt, reserveras ett minnesutrymme på 50 byte. Adressen för den första byten av reserverat utrymme tilldelas pekaren ptr av typen int.

Tänk på ett annat exempel på malloc-implementering:

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

Produktion:

Value of the 6th integer is 480

Observera att sizeof(*ptr) användes istället för sizeof(int) för att göra koden mer robust när *ptr-deklarationen typecastas till en annan datatyp senare.

Tilldelningen kan misslyckas om minnet inte räcker till. I det här fallet returnerar den en NULL-pekare. Så du bör inkludera kod för att leta efter en NULL-pekare.

Tänk på att det allokerade minnet är sammanhängande och kan behandlas som en array. Vi kan använda pekare aritmetik för att komma åt arrayelementen istället för att använda parenteser []. Vi rekommenderar att använda + för att referera till arrayelement eftersom användning av inkrementering ++ eller += ändrar adressen som lagras av pekaren.

Malloc-funktionen kan också användas med teckendatatypen såväl som komplexa datatyper som strukturer.

Varför använda malloc() i C?

Statiska arrayer och vanliga variabler fixerar sin storlek när programmet kompileras, vilket slösar utrymme när kravet visar sig vara mindre och misslyckas direkt när det visar sig vara större. malloc() löser detta genom att begära minne vid körning, så att ett program kan anpassa storleken på en buffert till den exakta mängd data det tar emot. Denna flexibilitet vid körning är kärnan i dynamisk minnesallokering i C.

Dynamisk allokering med malloc() är rätt val i flera vanliga situationer:

  • Mängden indata är okänd förrän programmet körs, till exempel när en fil eller en användarlevererad lista läses.
  • Stora block behövs som skulle överflöda den begränsade stacken, eftersom malloc() hämtar data från den mycket större heapen.
  • Data måste överleva den funktion som skapade den, eftersom heap-minnet kvarstår tills det explicit släpps.
  • Strukturer och arrayer måste växa eller krympa medan programmet körs.

Eftersom det reserverade blocket lämnas tillbaka som en pekare kan det skickas mellan funktioner billigt utan att kopiera underliggande data.

Hur man frigör minne allokerat av malloc()

Minne som reserveras av malloc() finns på heapen och frigörs aldrig automatiskt. När ett program fortsätter att allokera utan att frigöra, förbrukar det långsamt allt tillgängligt minne, en defekt som kallas minnesläcka. Funktionen free() returnerar ett färdigt block till systemet så att utrymmet kan återanvändas.

Funktionen free() tar ett enda argument, pekaren som malloc() returnerade, och släpper hela blocket på en gång:

int *ptr;
ptr = malloc(10 * sizeof(int));
if (ptr != NULL) {
    /* use the allocated memory here */
    free(ptr);   /* release the block */
    ptr = NULL;  /* avoid a dangling pointer */
}

Följ dessa regler för att hantera dynamiskt minne på ett säkert sätt:

  • Anropa free() exakt en gång för varje lyckad malloc(); att frigöra samma block två gånger orsakar odefinierat beteende.
  • Sätt pekaren till NULL efter frigöring så att den inte kan återanvändas som en dinglande pekare.
  • Frigör aldrig en pekare som malloc() inte returnerade, inklusive en som förskjutits av pekararitmetik.
  • Matcha varje allokering med en matchande release innan pekaren går utanför räckvidden.

keeping Balanserad allokering och frigöring är kärndisciplinen för manuell minneshantering i C, och det förhindrar både läckor och krascher orsakade av återanvändning av frigjort minne.

malloc() vs calloc(): Viktiga skillnader

malloc() och calloc() båda reserverar heap-minne, men de skiljer sig åt i sina argument och i hur de behandlar det nya blocket. malloc() tar ett argument, det totala antalet byte, och lämnar innehållet oinitierat, så blocket innehåller oförutsägbara skräpvärden tills programmet skriver till det. calloc() tar två argument, antalet element och storleken på varje, och rensar varje byte till noll innan pekaren returneras.

De praktiska skillnaderna kan handla om tre punkter:

  • Initialisering: calloc() nollställer minnet, medan malloc() inte gör det, vilket gör malloc() något snabbare när värdena ändå kommer att skrivas över.
  • Argument: du skriver malloc(n * size) men calloc(n, size) för att reservera samma array.
  • Användningsfall: välj calloc() när ett rent, nollställt block är viktigt, och malloc() när hastighet föredras och initialisering hanteras manuellt.

Båda funktionerna deklareras i stdlib.h, båda returnerar en void-pekare eller NULL vid fel, och båda lämnar tillbaka sitt minne med samma free()-funktion.

Vanliga frågor

I C är konverteringen valfri och avråds ofta, eftersom void* automatiskt konverterar till vilken objektpekare som helst och en explicit konvertering kan maskera en saknad stdlib.h include. C++, dock krävs rollbesättningen.

En NULL-retur innebär att begäran misslyckades, vanligtvis på grund av otillräckligt minne. Kontrollera alltid pekaren innan du använder den, eftersom avreferensering av NULL leder till odefinierat beteende och vanligtvis kraschar programmet.

realloc() ändrar storlek på ett block som tidigare reserverats av malloc(), keeping befintlig data upp till den mindre storleken. Om det misslyckas returnerar det NULL och lämnar det ursprungliga blocket intakt, så tilldela först dess resultat till en tillfällig pekare.

En minnesläcka uppstår när heapminne från malloc() aldrig frigörs med free(). Programmet fortsätter att reservera utrymme som det inte längre använder, vilket gradvis kan förbruka det tillgängliga minnet.

malloc() reserverar minne på heapen, inte stacken. Heapblock förblir giltiga tills du anropar free(), så de kan överleva funktionen som skapade dem, till skillnad från automatiska stackvariabler som försvinner vid retur.

malloc() är en biblioteksfunktion som returnerar void* och behöver sizeof för att beräkna byte. C++ new är en operator som returnerar en typad pekare och anropar konstruktorer. Para ihop malloc() med free() och new med delete.

Ja. AI-kodningsassistenter utarbetar malloc()-anrop, infogar NULL-kontroller och flaggar saknade free()-anrop eller läckor, och de kan förklara pekararitmetik. Kompilera och testa alltid den genererade koden innan du litar på den.

GitHub Copilot föreslår malloc(), sizeof() och matchande free()-rader från en kommentar som beskriver din avsikt. RevVisa varje förslag på saknade NULL-kontroller och läckor innan du kompilerar.

Sammanfatta detta inlägg med: