Alokacja pamięci: Różnice pomiędzy wersjami
m (Dodanie MetaData Description) |
m (cleanup bibliografii i rotten links) |
||
(Nie pokazano 8 wersji utworzonych przez 2 użytkowników) | |||
Linia 1: | Linia 1: | ||
==TL;DR== | ==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. | 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=== | ===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: | '''[[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 | * '''statyczny''' - alokacja pamięci następuje przed rozpoczęciem wykonywania programu | ||
* '''dynamiczny''' - alokacja następuje w fazie wykonywania programu | * '''dynamiczny''' - alokacja następuje w fazie wykonywania programu | ||
==Statyczna alokacja pamięci== | ==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ć: | 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ć: | ||
<pre> | <pre> | ||
# include<iostream.h> | # include<iostream.h> | ||
Linia 37: | Linia 20: | ||
tablica[4] = 24, | tablica[4] = 24, | ||
tablica[5] = 11, | tablica[5] = 11, | ||
<google>n</google> | |||
for (int i = 0; i <5; ++i){ | for (int i = 0; i <5; ++i){ | ||
suma += tablica[i]; | suma += tablica[i]; | ||
} | } | ||
cout<<"Suma liczb wynosi: "<<suma<<endl, | cout<<"Suma liczb wynosi: "<<suma<<endl, | ||
cin.get (), | cin.get (), | ||
return 0, | return 0, | ||
} | } | ||
</pre> | </pre> | ||
Wynikiem działania programu jest wyświetlenie na ekranie sumy poszczególnych elementów tablicy: | Wynikiem działania programu jest wyświetlenie na ekranie sumy poszczególnych elementów tablicy: | ||
<pre> | <pre> | ||
Suma liczb wynosi: 48 | Suma liczb wynosi: 48 | ||
</pre> | </pre> | ||
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: <pre>int tablica[5];</pre> Następnie poszczególnym elementom tablicy zostały przypisane wartości liczbowe: | 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: <pre>int tablica[5];</pre> Następnie poszczególnym elementom tablicy zostały przypisane wartości liczbowe: | ||
<pre>tablica[1] = 1, | <pre>tablica[1] = 1, | ||
tablica[2] = 4, | tablica[2] = 4, | ||
Linia 61: | Linia 45: | ||
tablica[4] = 24, | tablica[4] = 24, | ||
tablica[5] = 11;</pre> | tablica[5] = 11;</pre> | ||
Wykorzystując pętle '''for''' do zmiennej ''suma'' przypisana została suma wszystkich wartości poszczególnych elementów tablicy: | Wykorzystując pętle '''for''' do zmiennej ''suma'' przypisana została suma wszystkich wartości poszczególnych elementów tablicy: | ||
<pre> suma += tablica[i];</pre> | <pre> suma += tablica[i];</pre> | ||
==Dynamiczna alokacja pamięci== | ==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. | 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. | ||
Linia 75: | Linia 58: | ||
int * ind, | int * ind, | ||
ind = new int[8], | ind = new int[8], | ||
if (!ind) | if (!ind) | ||
cout<<Alokacja zakonczona niepowodzeniem", | cout<<Alokacja zakonczona niepowodzeniem", | ||
Linia 97: | Linia 80: | ||
===Operator new=== | ===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ć: | 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ć: | ||
<pre> | <pre> | ||
Linia 103: | Linia 85: | ||
</pre> | </pre> | ||
* '''ind''' - wskaźnik do pamięci alokowanej ze sterty | * '''ind''' - wskaźnik do pamięci alokowanej ze sterty | ||
* '''new''' - przydzielenie pamięci i zwrócenie wskaźnika do jej początku | * '''new''' - przydzielenie pamięci i zwrócenie wskaźnika do jej początku | ||
* '''type''' - typ deklarowanej zmiennej | * '''type''' - typ deklarowanej zmiennej | ||
Przykładowa [[instrukcja]] wykorzystująca alokację pamięci, zainicjowana z wartością początkową 10: | Przykładowa [[instrukcja]] wykorzystująca alokację pamięci, zainicjowana z wartością początkową 10: | ||
<pre> | <pre> | ||
int* ind = new int (10), | int* ind = new int (10), | ||
Linia 114: | Linia 96: | ||
===Operator delete=== | ===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''. | 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ć: | Składnia operacji zwalniania pamięci ma postać: | ||
Linia 122: | Linia 103: | ||
gdzie ''ind'' oznacza wskaźnik do typu o nazwie ''type''. | 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]]. | 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]]. | ||
{{infobox5|list1={{i5link|a=[[Programowanie]]}} — {{i5link|a=[[GERT]]}} — {{i5link|a=[[Ganttproject]]}} — {{i5link|a=[[Prosty program]]}} — {{i5link|a=[[SmallTalk (język programowania)]]}} — {{i5link|a=[[Odśmiecanie pamięci]]}} — {{i5link|a=[[Programowanie strukturalne]]}} — {{i5link|a=[[C (język programowania)]]}} — {{i5link|a=[[CAD]]}} }} | |||
==Bibliografia== | ==Bibliografia== | ||
* Michelsen | <noautolinks> | ||
* Porębski | * Michelsen K. (2007), ''Język C#. Szkoła programowania'', Helion, Gliwice | ||
* Prata | * 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 | * Russek P., Wiatr K. (2005), ''[https://yadda.icm.edu.pl/baztech/element/bwmeta1.element.baztech-article-AGH1-0006-0016/c/Russek.pdf 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 | |||
</noautolinks> | |||
[[Kategoria:Języki_programowania]] | [[Kategoria:Języki_programowania]] | ||
{{a|Jarosław Wachel}} | {{a|Jarosław Wachel}} | ||
{{#metamaster:description|Alokacja pamięci | {{#metamaster:description|Alokacja pamięci - proces przydzielania i zarządzania pamięcią w komputerze. Dowiedz się, jak działa i jakie są różne metody alokacji pamięci.}} |
Aktualna wersja na dzień 20:38, 17 gru 2023
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