Alokacja pamięci

Alokacja pamięci
Polecane artykuły

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,
 
 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.

Bibliografia

Autor: Jarosław Wachel