Chciałbym wiedzieć, jaka jest różnica między statyczną alokacją pamięci a dynamiczną alokacją pamięci?
Czy mógłbyś to wyjaśnić na jakimkolwiek przykładzie?
Chciałbym wiedzieć, jaka jest różnica między statyczną alokacją pamięci a dynamiczną alokacją pamięci?
Czy mógłbyś to wyjaśnić na jakimkolwiek przykładzie?
Odpowiedzi:
Istnieją trzy typy alokacji - statyczne, automatyczne i dynamiczne.
Przydział statyczny oznacza, że pamięć dla zmiennych jest przydzielana podczas uruchamiania programu. Rozmiar jest ustalany podczas tworzenia programu. Dotyczy to zmiennych globalnych, zmiennych o zasięgu pliku i zmiennych kwalifikowanych za pomocą static
zdefiniowanych wewnątrz funkcji.
Automatyczna alokacja pamięci ma miejsce dla (niestatycznych) zmiennych zdefiniowanych w funkcjach i zwykle jest przechowywana na stosie (chociaż standard C nie nakazuje używania stosu). Nie musisz rezerwować dodatkowej pamięci za ich pomocą, ale z drugiej strony masz również ograniczoną kontrolę nad żywotnością tej pamięci. Np .: zmienne automatyczne w funkcji są dostępne tylko do zakończenia funkcji.
void func() {
int i; /* `i` only exists during `func` */
}
Dynamiczna alokacja pamięci jest nieco inna. Teraz możesz kontrolować dokładny rozmiar i żywotność tych lokalizacji w pamięci. Jeśli go nie zwolnisz, napotkasz wycieki pamięci, które mogą spowodować awarię aplikacji, ponieważ w pewnym momencie system nie może przydzielić większej ilości pamięci.
int* func() {
int* mem = malloc(1024);
return mem;
}
int* mem = func(); /* still accessible */
W górnym przykładzie przydzielona pamięć jest nadal ważna i dostępna, mimo że funkcja została zakończona. Kiedy skończysz z pamięcią, musisz ją zwolnić:
free(mem);
To jest standardowe pytanie do wywiadu:
Czy pamięć przydzielona w czasie wykonywania przy użyciu calloc()
, malloc()
i przyjaciół. Czasami jest również nazywana pamięcią „sterty”, chociaż nie ma to nic wspólnego z referencją struktury danych sterty .
int * a = malloc(sizeof(int));
Pamięć sterty jest trwała do momentu free()
wywołania. Innymi słowy, kontrolujesz okres istnienia zmiennej.
Jest to tak zwana pamięć „stosu” i jest ona przydzielana, gdy wprowadzasz nowy zakres (zwykle, gdy nowa funkcja jest umieszczana na stosie wywołań). Po wyjściu z zakresu wartości automatycznych adresów pamięci są nieokreślone i dostęp do nich jest błędem .
int a = 43;
Zauważ, że zasięg niekoniecznie oznacza funkcję. Zakresy mogą zagnieżdżać się w funkcji, a zmienna będzie w zakresie tylko w bloku, w którym została zadeklarowana. Należy również zauważyć, że nie określono miejsca, w którym ta pamięć jest przydzielona. (W rozsądnym systemie będzie na stosie lub w rejestrach do optymalizacji)
Jest przydzielany w czasie kompilacji * , a okres istnienia zmiennej w pamięci statycznej jest okresem istnienia programu .
W języku C pamięć statyczną można przydzielić za pomocą static
słowa kluczowego. Zakres jest tylko jednostką kompilacji.
Sprawy stają się bardziej interesujące, gdy extern
weźmie się pod uwagę słowo kluczowe . Gdy extern
zmienna jest zdefiniowana, kompilator przydziela jej pamięć. Kiedy deklarowanaextern
jest zmienna , kompilator wymaga, aby zmienna była zdefiniowana w innym miejscu. Brak zadeklarowania / zdefiniowania zmiennych spowoduje problemy z łączeniem, a brak zadeklarowania / zdefiniowania zmiennych spowoduje problemy z kompilacją.extern
static
w zakresie pliku słowo kluczowe static jest opcjonalne (poza funkcją):
int a = 32;
Ale nie w zakresie funkcji (wewnątrz funkcji):
static int a = 32;
Technicznie extern
i static
są dwiema oddzielnymi klasami zmiennych w C.
extern int a; /* Declaration */
int a; /* Definition */
Trochę mylące jest stwierdzenie, że pamięć statyczna jest przydzielana w czasie kompilacji, zwłaszcza jeśli zaczniemy rozważać, że maszyna kompilująca i maszyna hosta mogą nie być takie same lub mogą nawet nie być na tej samej architekturze.
Lepszym rozwiązaniem może być myślenie, że alokacja pamięci statycznej jest obsługiwana przez kompilator, a nie przydzielana w czasie kompilacji .
Na przykład kompilator może utworzyć dużą data
sekcję w skompilowanym pliku binarnym, a gdy program jest załadowany do pamięci, adres wdata
segment programu zostanie użyty jako lokalizacja przydzielonej pamięci. Ma to wyraźną wadę polegającą na tym, że skompilowany plik binarny jest bardzo duży, jeśli używa dużo pamięci statycznej. Możliwe jest napisanie wielogigabajtowego pliku binarnego wygenerowanego z mniej niż pół tuzina linii kodu. Inną opcją jest dla kompilatora wstrzyknięcie kodu inicjującego, który przydzieli pamięć w inny sposób, zanim program zostanie wykonany. Ten kod będzie się różnić w zależności od platformy docelowej i systemu operacyjnego. W praktyce współczesne kompilatory używają heurystyki, aby zdecydować, której z tych opcji użyć. Możesz to wypróbować samodzielnie, pisząc mały program w języku C, który przydziela dużą tablicę statyczną zawierającą elementy 10k, 1m, 10m, 100m, 1G lub 10G. W przypadku wielu kompilatorów rozmiar binarny będzie wzrastał liniowo wraz z rozmiarem tablicy i przekroczy określony punkt,
Ostatnią klasą pamięci są zmienne „rejestrowe”. Zgodnie z oczekiwaniami, zmienne rejestrowe powinny być alokowane w rejestrze procesora, ale decyzja należy do kompilatora. Nie możesz zamienić zmiennej rejestrowej w odniesienie za pomocą adresu.
register int meaning = 42;
printf("%p\n",&meaning); /* this is wrong and will fail at compile time. */
Większość nowoczesnych kompilatorów jest mądrzejsza od Ciebie w wybieraniu zmiennych, które powinny być umieszczone w rejestrach :)
int * a = malloc(sizeof(*a));
zamiast tego sugerowałbym unikanie powtarzania typu a
. To znacznie ułatwia sprawę, jeśli kiedykolwiek rodzaj a
zmian.
Przydział pamięci statycznej:
Dynamiczna alokacja pamięci:
Statyczna alokacja pamięci: kompilator przydziela wymaganą przestrzeń pamięci dla zadeklarowanej zmiennej, korzystając z adresu operatora, uzyskuje się zarezerwowany adres, który może być przypisany do zmiennej wskaźnikowej, ponieważ większość zadeklarowanych zmiennych ma pamięć statyczną, sposób przypisywania wartości wskaźnika do zmiennej wskaźnikowej jest znany jako statyczna alokacja pamięci. pamięć jest przypisywana podczas kompilacji.
Dynamiczna alokacja pamięci: wykorzystuje funkcje takie jak malloc () lub calloc () do dynamicznego uzyskiwania pamięci.Jeśli te funkcje są używane do dynamicznego uzyskiwania pamięci, a wartości zwracane przez te funkcje są przypisywane do zmiennych wskaźnikowych, takie przypisania są znane jako pamięć dynamiczna Alokacja. pamięć jest przydzielana w czasie wykonywania.
Różnica między statyczna pamięć PRZYDZIELANIA & pamięć dynamiczna PRZYDZIELANIA
Pamięć jest przydzielana przed rozpoczęciem wykonywania programu (podczas kompilacji).
Pamięć jest przydzielana podczas wykonywania programu.
Podczas wykonywania nie są wykonywane żadne akcje alokacji ani zwalniania pamięci.
Powiązania pamięci są ustanawiane i niszczone podczas wykonywania.
Zmienne pozostają na stałe przydzielone.
Przydzielane tylko wtedy, gdy jednostka programu jest aktywna.
Realizowane za pomocą stosów i stert.
Wdrożone przy użyciu segmentów danych.
Aby uzyskać dostęp do zmiennych, potrzebny jest wskaźnik.
Nie ma potrzeby dynamicznie przydzielanych wskaźników.
Szybsze wykonanie niż dynamiczne.
Wolniejsze wykonanie niż statyczne.
Wymagane więcej miejsca w pamięci.
Wymagana mniejsza ilość miejsca w pamięci.
Przydział pamięci statycznej jest przydzielany w pamięci przed wykonaniem programu pf w czasie kompilacji. Dynamiczna alokacja pamięci to pamięć alokowana podczas wykonywania programu w czasie wykonywania.