Alokacja pamięci
TL;DR
Artykuł omawia statyczną i dynamiczną alokację pamięci. Statyczna alokacja pamięci następuje przed rozpoczęciem programu i wymaga wcześniejszego przewidzenia potrzebnego obszaru pamięci. Dynamiczna alokacja pamięci pozwala na dostosowanie wielkości przestrzeni pamięci do bieżących potrzeb programu. W języku C++ alokacja pamięci odbywa się za pomocą operatora "new", a zwalnianie pamięci za pomocą operatora "delete". Operator "new" tworzy obiekt i zwraca wskaźnik do alokowanej pamięci, a operator "delete" niszczy obiekt i zwalnia pamięć. Unikanie wielokrotnego zwalniania tego samego obszaru pamięci jest ważne. Istnieją języki, które automatycznie zarządzają odzyskiwaniem pamięci.
Definicja
Alokacja pamięci - przydzielenie obiektowi pewnego obszaru pamięci oraz nadanie mu wartości początkowej. System operacyjny przydziela pulę wolnej pamięci, która może zostać wykorzystana przez program. Alokacja pamięci zasadniczo może przebiegać na dwa sposoby:
- statyczny - alokacja pamięci następuje przed rozpoczęciem wykonywania programu
- dynamiczny - alokacja następuje w fazie wykonywania programu
Statyczna alokacja pamięci
W przypadku wykorzystania metody statycznej, pamięć zostaje przydzielona przed rozpoczęciem wykonywania programu i istnieje aż do momentu jego zakończenia. Zwalnianie pamięci następuje automatycznie po zakończeniu programu. Zasadniczym problemem przy wykorzystaniu tej metody jest konieczność wcześniejszego przewidzenia wielkości obszaru pamięci jaki będzie potrzebny do przechowania danych programu, co przy nawet najprostszych programach jest znaczącym utrudnieniem. Prosty program napisany w języku C++ pokazujący działanie statycznej alokacji pamięci ma postać:
# include<iostream.h> int main (){ int tablica[5], int suma = 0, tablica[1] = 1, tablica[2] = 4, tablica[3] = 8, tablica[4] = 24, tablica[5] = 11, <google>n</google> for (int i = 0; i <5; ++i){ suma += tablica[i]; } cout<<"Suma liczb wynosi: "<<suma<<endl, cin.get (), return 0, }
Wynikiem działania programu jest wyświetlenie na ekranie sumy poszczególnych elementów tablicy:
Suma liczb wynosi: 48
W powyższym przykładzie zastosowana zastosowana została metoda statyczna alokacji pamięci, w której dla tablicy jednowymiarowej już w fazie deklaracji zmiennych przypisany został jej rozmiar:
int tablica[5];
Następnie poszczególnym elementom tablicy zostały przypisane wartości liczbowe:
tablica[1] = 1, tablica[2] = 4, tablica[3] = 8, tablica[4] = 24, tablica[5] = 11;
Wykorzystując pętle for do zmiennej suma przypisana została suma wszystkich wartości poszczególnych elementów tablicy:
suma += tablica[i];
Dynamiczna alokacja pamięci
Wykorzystanie mechanizmu dynamicznej alokacji pamięci ma na celu dostosowanie wielkości zarezerwowanej przestrzeni pamięci do potrzeb jakie w danej chwili ma program. Mechanizm ten pozwala na na manipulowanie danymi o zmiennej wielkości co znacząco zwiększa elastyczność programu. Pamięć alokowana jest z puli pamięci zwanej stertą (część pamięci operacyjnej niewykorzystana przez program w momencie jego uruchomienia) - oznacza to, że czas życia danego obiektu nie jest ograniczony przez jego zasięg. Zasadniczą zaletą takiego rozwiązania jest dynamiczne rozszerzanie zapotrzebowania na pamięć w zależności od potrzeb oraz przydzielanie ze sterty tyle pamięci ile w danej chwili jest potrzebne.
Poniżej przedstawiony został przykładowy program wykorzystujący dynamiczną alokację pamięci:
# include<iostream.h> int main () { int * ind, ind = new int[8], if (!ind) cout<<Alokacja zakonczona niepowodzeniem", cout<<endl, return 1, for (int i=0;i<8;i++) { ind[i] = i, for (int j=0; j<8;j++) { cout<<"ind["<<j<<"]: ", cout<<ind[j], cout<<endl, } delete [] ind, return 0, }
Operator new
W przypadku języka C++ alokacji pamięci dokonuje się za pomocą operatora new, po którym następuje nazwa typu (szczególnym przypadkiem są tablice, dla których stosuje się wyrażenie new typ[rozmiarTablicy]). Operator new zwraca wskaźnik do miejsca w pamięci w której została dokonana alokacja. W najprostszej postaci składnia instrukcji alokacji pamięci ma postać:
type* ind = new type,
- ind - wskaźnik do pamięci alokowanej ze sterty
- new - przydzielenie pamięci i zwrócenie wskaźnika do jej początku
- type - typ deklarowanej zmiennej
Przykładowa instrukcja wykorzystująca alokację pamięci, zainicjowana z wartością początkową 10:
int* ind = new int (10),
Nadrzędnym zadaniem operatora new jest utworzenie obiektu typu type. Gdy utworzenie obiektu zakończy się sukcesem - dla obiektu typy type zostanie przydzielona pamięć, new zwraca wskaźnik do tego obiektu, który zawarty jest w zmiennej wskaźnikowej ind.
Operator delete
Zadaniem operatora delete jest zniszczenie obiektu utworzonego przez operator new i zwrócenie zwolnionej pamięci do puli pamięci dostępnej do ponownego wykorzystania. Po wykonaniu operacji delete wartość wskaźnika jest określona jako 0 lub null. Składnia operacji zwalniania pamięci ma postać:
delete ind,
gdzie ind oznacza wskaźnik do typu o nazwie type.
W przypadku operatora delete ważne jest unikanie wielokrotnego zwalniania tego samego obszaru pamięci. Skutkuje to późniejszymi problemami przy wykonywaniu programu. Rozwiązaniem tego problemu jest jest wykorzystanie wartości null przed każdym użyciem wskaźnika oraz po każdym zwolnieniu wskazywanego przez niego obszaru pamięci. Dzięki temu adres przekazany we wskaźniku zostanie uznany jako nieważny w przypadku ponownego użycia względem niego operatora delete. Istnieje szereg języków wysokiego poziomu, które oferują zintegrowane mechanizmy odśmiecania pamięci (garbage collector), który automatycznie zajmuje się odzyskiwaniem pamięci. Przykładem takiego języka jest Java czy szereg języków skryptowych takich jak Python czy PHP.
Alokacja pamięci — artykuły polecane |
Programowanie — GERT — Ganttproject — Prosty program — SmallTalk (język programowania) — Odśmiecanie pamięci — Programowanie strukturalne — C (język programowania) — CAD |
Bibliografia
- Michelsen K. (2007), Język C#. Szkoła programowania, Helion, Gliwice
- Porębski W. (2008), Język C++ Standard ISO w praktyce, Wydawnictwo Naukowe PWN, Warszawa
- Prata S. (2006), Język C++. Szkoła programowania, Helion, Gliwice
- Russek P., Wiatr K. (2005), Perspektywy przyśpieszenia obliczeń w instalacjach o wielkich mocach obliczeniowych za pomocą układów logiki rekonfigurowalnej, Automatyka/Akademia Górniczo-Hutnicza im. Stanisława Staszica w Krakowie, 9
- Van Roy P. (2005), Programowanie. Koncepcje, techniki i modele, Helion, Gliwice
Autor: Jarosław Wachel