malloc() Функция в C библиотека с ПРИМЕР

⚡ Умно обобщение

malloc() в C резервира блок памет в heap-а по време на изпълнение и връща void указател към първия му байт, позволявайки на програмите да изискват памет, чийто размер е неизвестен, докато кодът действително не се изпълни.

  • 🧠 Разпределение по време на изпълнение: malloc() резервира памет по време на изпълнение, когато необходимият размер не е известен по време на компилация.
  • 📦 Синтаксис: Указателят тип cast получава malloc(byte_size), обикновено оразмерен с sizeof за преносимост.
  • ⚠️ NULL проверка: Неуспешна заявка връща NULL указател, така че валидирайте резултата, преди да го разреференцирате.
  • Аритметика на указателите: Блокът е съседен, така че използвайте +, а не ++, за да достигнете до елементите на масива.
  • 🧹 Освободете паметта: Освободете всеки блок с free(), за да предотвратите изтичане на памет и висящи указатели.
  • 🤖 AI помощ: AI асистентите и GitHub Copilot изготвят malloc() извиквания и маркират липсващи free() оператори.

Функция malloc() в C

Какво е malloc в C?

Функцията malloc() означава разпределение на паметта. Това е функция, която се използва за динамично разпределяне на блок памет. Той запазва място в паметта с определен размер и връща нулевия указател, сочещ към мястото в паметта. Върнатият указател обикновено е от тип void. Това означава, че можем да присвоим функция malloc на всеки указател.

Какво е malloc в C

Синтаксис

ptr = (cast_type *) malloc (byte_size);

Тук

  • ptr е указател на cast_type.
  • Функцията malloc връща указател към разпределената памет на byte_size.
Example: ptr = (int *) malloc (50)

Когато този оператор се изпълни успешно, се запазва място в паметта от 50 байта. Адресът на първия байт от запазеното пространство се присвоява на указателя ptr от тип int.

Помислете за друг пример за изпълнение на malloc:

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

Изход:

Value of the 6th integer is 480

Обърнете внимание, че вместо sizeof(int) е използвано sizeof(*ptr), за да се направи кодът по-стабилен, когато декларацията *ptr бъде преобразувана в различен тип данни по-късно.

Разпределението може да се провали, ако паметта не е достатъчна. В този случай той връща NULL указател. Така че трябва да включите код за проверка за NULL указател.

Имайте предвид, че разпределената памет е съседна и може да се третира като масив. Можем да използваме показалка аритметика за достъп до елементите на масива, вместо използване на скоби []. Препоръчваме да използвате + за обозначаване на елементи от масива, защото използването на инкрементация ++ или += променя адреса, съхранен от показалеца.

Функцията Malloc може да се използва и със символен тип данни, както и със сложни типове данни, като например структури.

Защо да използваме malloc() в C?

Статичните масиви и обикновените променливи фиксират размера си при компилиране на програмата, което води до загуба на място, когато изискването се окаже по-малко, и се проваля напълно, когато се окаже по-голямо. malloc() решава това, като изисква памет по време на изпълнение, така че програмата може да оразмери буфера до точното количество данни, които получава. Тази гъвкавост по време на изпълнение е сърцевината на динамично разпределение на паметта в С.

Динамичното разпределение с malloc() е правилният избор в няколко често срещани ситуации:

  • Количеството входни данни е неизвестно, докато програмата не се изпълни, например при четене на файл или списък, предоставен от потребителя.
  • Необходими са големи блокове, които биха препълнили ограничения стек, тъй като malloc() черпи от много по-големия стек.
  • Данните трябва да надживеят функцията, която ги е създала, защото heap паметта се запазва, докато не бъде изрично освободена.
  • Структурите и масивите трябва да се увеличават или намаляват, докато програмата се изпълнява.

Тъй като резервираният блок се връща като указател, той може да се предава между функции евтино, без да се копират основните данни.

Как да освободим памет, разпределена от malloc()

Паметта, резервирана от malloc(), се намира в heap-а и никога не се освобождава автоматично. Когато една програма продължава да разпределя памет, без да я освобождава, тя бавно изразходва цялата налична памет – дефект, известен като изтичане на памет. Функцията free() връща завършен блок на системата, така че пространството може да се използва повторно.

Функцията free() приема един аргумент, указателя, върнат от malloc(), и освобождава целия блок наведнъж:

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 */
}

Следвайте тези правила, за да управлявате безопасно динамичната памет:

  • Извикайте free() точно веднъж за всяка успешна операция malloc(); освобождаването на един и същ блок два пъти води до неопределено поведение.
  • Задайте указателя на NULL след освобождаване, така че да не може да бъде използван повторно като висящ указател.
  • Никога не освобождава() указател, който malloc() не е върнал, включително такъв, изместен чрез аритметика на указателите.
  • Съпоставете всяко разпределение със съответстващо освобождаване, преди показалецът да излезе извън обхвата.

Keeping Разпределението и освобождаването в баланс е основната дисциплина на ръчното управление на паметта в C и предотвратява както течове, така и сривове, причинени от повторно използване на освободената памет.

malloc() срещу calloc(): Ключови разлики

malloc() и calloc() И двата резервират памет в купчината, но се различават по аргументите си и по начина, по който третират новия блок. malloc() приема един аргумент - общия брой байтове, и оставя съдържанието неинициализирано, така че блокът съдържа непредсказуеми стойности, докато програмата не запише в него. calloc() приема два аргумента - броя на елементите и размера на всеки от тях, и изчиства всеки байт до нула, преди да върне показалеца.

Практическите разлики се свеждат до три точки:

  • Инициализация: calloc() нулира паметта, докато malloc() не го прави, което прави malloc() малко по-бърз, когато стойностите така или иначе ще бъдат презаписани.
  • Аргументи: пишете malloc(n * size), но calloc(n, size), за да резервирате същия масив.
  • Случай на употреба: изберете calloc(), когато чист, нулиран блок е от значение, и malloc(), когато скоростта е предпочитана и инициализацията се обработва ръчно.

И двете функции са декларирани в stdlib.h, и двете връщат void указател или NULL при неуспех и двете връщат паметта си обратно с една и съща функция free().

Въпроси и Отговори

В C преобразуването е по избор и често се не препоръчва, защото void* автоматично се преобразува във всеки указател на обект, а изричното преобразуване може да маскира липсващо включено в stdlib.h. В C++, обаче, актьорският състав е задължителен.

Връщането на NULL означава, че заявката е неуспешна, обикновено поради недостатъчна памет. Винаги проверявайте показалеца, преди да го използвате, защото разреференцирането на NULL води до неопределено поведение и обикновено води до срив на програмата.

realloc() преоразмерява блок, предварително резервиран от malloc(), keeping съществуващи данни до по-малък размер. Ако не успее, връща NULL и оставя оригиналния блок непокътнат, така че първо присвоете резултата му на временен указател.

Изтичане на памет се случва, когато heap паметта от malloc() никога не се освобождава с free(). Програмата продължава да резервира пространство, което вече не използва, което постепенно може да изчерпи наличната памет.

malloc() резервира памет в heap-а, а не в стека. Heap блоковете остават валидни, докато не извикате free(), така че те могат да надживеят функцията, която ги е създала, за разлика от автоматичните стекови променливи, които изчезват при връщане.

malloc() е библиотечна функция, която връща void* и се нуждае от sizeof, за да изчисли байтовете. C++ new е оператор, който връща типизиран указател и извиква конструктори. Свържете malloc() с free(), а new с delete.

Да. Асистентите по кодиране с изкуствен интелект изготвят извиквания на malloc(), вмъкват NULL проверки и маркират липсващи извиквания или течове на free() и могат да обяснят аритметиката на пойнтерите. Винаги компилирайте и тествайте генерирания код, преди да му се доверите.

Копилот на GitHub предлага malloc(), sizeof() и съответстващи free() редове от коментар, описващ вашето намерение. RevПрегледайте всяко предложение за липсващи NULL проверки и течове, преди да компилирате.

Обобщете тази публикация с: