Funkcja malloc() w bibliotece C z PRZYKŁADEM
⚡ Inteligentne podsumowanie
Funkcja malloc() w języku C rezerwuje blok pamięci na stercie w czasie wykonywania i zwraca wskaźnik typu void do jego pierwszego bajtu, umożliwiając programom żądanie pamięci, której rozmiar jest nieznany do momentu faktycznego wykonania kodu.
Co to jest malloc w C?
Funkcja malloc() oznacza alokację pamięci. Jest to funkcja służąca do dynamicznego przydzielania bloku pamięci. Rezerwuje przestrzeń pamięci o określonym rozmiarze i zwraca wskaźnik zerowy wskazujący lokalizację pamięci. Zwracany wskaźnik jest zwykle typu void. Oznacza to, że możemy przypisać funkcję malloc do dowolnego wskaźnika.
Składnia
ptr = (cast_type *) malloc (byte_size);
Tutaj,
- ptr jest wskaźnikiem typu rzutu.
- Funkcja malloc zwraca wskaźnik do przydzielonej pamięci o rozmiarze bajtu.
Example: ptr = (int *) malloc (50)
Po pomyślnym wykonaniu tej instrukcji rezerwowana jest pamięć o wielkości 50 bajtów. Adres pierwszego bajtu zarezerwowanej przestrzeni jest przypisany do wskaźnika ptr typu int.
Rozważ inny przykład implementacji 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)); } }
Wyjście:
Value of the 6th integer is 480
Należy zauważyć, że użyto sizeof(*ptr) zamiast sizeof(int), aby kod był bardziej odporny, gdy deklaracja *ptr zostanie później rzutowana na inny typ danych.
Alokacja może się nie powieść, jeśli pamięć nie jest wystarczająca. W tym przypadku zwraca wskaźnik NULL. Powinieneś więc dołączyć kod sprawdzający wskaźnik NULL.
Należy pamiętać, że przydzielona pamięć jest ciągła i można ją traktować jak tablicę. Możemy użyć wskaźnik arytmetyki do dostępu do elementów tablicy zamiast używania nawiasów [ ]. Zalecamy używanie znaku + do odwoływania się do elementów tablicy, ponieważ użycie inkrementacji ++ lub += zmienia adres przechowywany przez wskaźnik.
Funkcji Malloc można używać również z typami danych znakowych oraz złożonymi typami danych, takimi jak struktury.
Dlaczego warto używać malloc() w C?
Tablice statyczne i zwykłe zmienne ustalają swój rozmiar podczas kompilacji programu, co marnuje miejsce, gdy wymagania stają się mniejsze, i całkowicie kończy się niepowodzeniem, gdy stają się większe. Funkcja malloc() rozwiązuje ten problem, żądając pamięci w czasie wykonywania, dzięki czemu program może dostosować rozmiar bufora do dokładnej ilości danych, które otrzymuje. Ta elastyczność w czasie wykonywania jest sercem dynamiczna alokacja pamięci w C.
Dynamiczna alokacja z wykorzystaniem funkcji malloc() jest właściwym wyborem w kilku typowych sytuacjach:
- Ilość danych wejściowych nie jest znana do momentu uruchomienia programu, np. odczytania pliku lub listy dostarczonej przez użytkownika.
- Potrzebne są duże bloki, które przepełniłyby ograniczony stos, ponieważ malloc() czerpie dane ze znacznie większego stosu.
- Dane muszą przetrwać funkcję, która je utworzyła, ponieważ pamięć sterty jest zachowywana do momentu jej jawnego zwolnienia.
- Struktury i tablice muszą się powiększać lub zmniejszać podczas wykonywania programu.
Ponieważ zarezerwowany blok jest zwracany w postaci wskaźnika, można go tanio przekazywać między funkcjami, bez konieczności kopiowania danych bazowych.
Jak zwolnić pamięć przydzieloną przez malloc()
Pamięć zarezerwowana przez funkcję malloc() znajduje się na stercie i nigdy nie jest automatycznie zwalniana. Gdy program stale alokuje pamięć bez jej zwalniania, powoli zużywa całą dostępną pamięć – jest to defekt znany jako wyciek pamięci. Funkcja free() zwraca systemowi ukończony blok, aby przestrzeń mogła zostać ponownie wykorzystana.
Funkcja free() przyjmuje pojedynczy argument – wskaźnik zwrócony przez funkcję malloc() – i natychmiast zwalnia cały blok:
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 */ }
Aby bezpiecznie zarządzać pamięcią dynamiczną, postępuj zgodnie z poniższymi zasadami:
- Wywołuj free() dokładnie raz dla każdego pomyślnego zwolnienia funkcji malloc(); dwukrotne zwolnienie tego samego bloku powoduje niezdefiniowane zachowanie.
- Po zwolnieniu ustaw wskaźnik na NULL, aby nie można było go ponownie wykorzystać jako wskaźnika wiszącego.
- Nigdy nie zwalniaj wskaźnika, którego nie zwróciła funkcja malloc(), w tym wskaźnika przesuniętego przez arytmetykę wskaźników.
- Dopasuj każdą alokację do pasującej wersji zanim wskaźnik wyjdzie poza zakres.
Keeping równomierne przydzielanie i zwalnianie pamięci stanowi podstawę ręcznego zarządzania pamięcią w języku C. Zapobiega to wyciekom i awariom spowodowanym przez ponowne wykorzystanie zwolnionej pamięci.
malloc() vs calloc(): kluczowe różnice
malloc() i kaloc() obie funkcje rezerwują pamięć sterty, ale różnią się argumentami i sposobem, w jaki traktują nowy blok. malloc() przyjmuje jeden argument, całkowitą liczbę bajtów, i pozostawia zawartość niezainicjowaną, więc blok przechowuje nieprzewidywalne wartości śmieci, dopóki program do niego nie zapisze. calloc() przyjmuje dwa argumenty, liczbę elementów i rozmiar każdego z nich, i czyści każdy bajt do zera przed zwróceniem wskaźnika.
Praktyczne różnice sprowadzają się do trzech punktów:
- Inicjalizacja: calloc() zeruje pamięć, podczas gdy malloc() tego nie robi, co sprawia, że malloc() działa odrobinę szybciej, gdy wartości i tak zostaną nadpisane.
- Argumenty: piszesz malloc(n * size), ale calloc(n, size) aby zarezerwować tę samą tablicę.
- Przypadek użycia: wybierz calloc(), gdy liczy się czysty, wyzerowany blok, a malloc(), gdy zależy Ci na szybkości, a inicjalizacja jest obsługiwana ręcznie.
Obie funkcje są zadeklarowane w stdlib.h, obie zwracają wskaźnik typu void lub wartość NULL w przypadku błędu i obie przekazują swoją pamięć za pomocą tej samej funkcji free().


