Istnieją dwa miejsca, w których można umieścić zmienne w pamięci. Podczas tworzenia takiej zmiennej:
int a;
char c;
char d[16];
Zmienne tworzone są w „ stosie ”. Zmienne stosu są automatycznie zwalniane, gdy wyjdą poza zakres (to znaczy, gdy kod nie może już do nich dotrzeć). Możesz usłyszeć, że to zmienne „automatyczne”, ale to wyszło z mody.
Wiele przykładów dla początkujących wykorzystuje tylko zmienne stosu.
Stos jest fajny, ponieważ jest automatyczny, ale ma również dwie wady: (1) kompilator musi wiedzieć z wyprzedzeniem, jak duże są zmienne, oraz (b) przestrzeń stosu jest nieco ograniczona. Na przykład: w systemie Windows, przy domyślnych ustawieniach konsolidatora Microsoft, stos jest ustawiony na 1 MB, a nie całość jest dostępna dla zmiennych.
Jeśli w czasie kompilacji nie wiesz, jak duża jest twoja tablica lub jeśli potrzebujesz dużej tablicy lub struktury, potrzebujesz „planu B”.
Plan B nazywany jest „ stertą ”. Zwykle możesz tworzyć zmienne tak duże, jak pozwala na to system operacyjny, ale musisz to zrobić sam. Wcześniejsze posty pokazały, że możesz to zrobić, chociaż są też inne sposoby:
int size;
char *p = (char *)malloc(size);
(Zwróć uwagę, że zmiennymi w stercie nie można manipulować bezpośrednio, ale za pomocą wskaźników)
Po utworzeniu zmiennej sterty problem polega na tym, że kompilator nie może powiedzieć, kiedy z nią skończysz, więc tracisz automatyczne zwalnianie. W tym miejscu pojawia się „ręczne zwalnianie”, o którym mówiłaś. Twój kod jest teraz odpowiedzialny za podjęcie decyzji, kiedy zmienna nie jest już potrzebna, i zwolnienie jej, aby pamięć mogła zostać wykorzystana do innych celów. W powyższym przypadku z:
free(p);
To, co sprawia, że ta druga opcja jest „paskudną sprawą”, to fakt, że nie zawsze łatwo jest stwierdzić, kiedy zmienna nie jest już potrzebna. Zapomnienie o zwolnieniu zmiennej, gdy jej nie potrzebujesz, spowoduje, że program zużyje więcej pamięci niż potrzebuje. Taka sytuacja nazywana jest „wyciekiem”. „Wyciekła” pamięć nie może być użyta do niczego, dopóki program się nie zakończy, a system operacyjny nie odzyska wszystkich swoich zasobów. Jeszcze bardziej nieprzyjemne problemy są możliwe, jeśli przez pomyłkę zwolnisz zmienną sterty, zanim faktycznie skończysz z nią.
W C i C ++ jesteś odpowiedzialny za wyczyszczenie zmiennych sterty, jak pokazano powyżej. Istnieją jednak języki i środowiska, takie jak języki Java i .NET, takie jak C #, które wykorzystują inne podejście, w którym sterta jest czyszczona samodzielnie. Ta druga metoda, zwana „wyrzucaniem elementów bezużytecznych”, jest znacznie łatwiejsza dla dewelopera, ale wiąże się to z obniżeniem kosztów i wydajności. To równowaga.
(Przeanalizowałem wiele szczegółów, aby dać prostszą, ale miejmy nadzieję, bardziej wyrównaną odpowiedź)