• Nie Znaleziono Wyników

Krtko o zarzdzaniu pamieci

N/A
N/A
Protected

Academic year: 2021

Share "Krtko o zarzdzaniu pamieci"

Copied!
13
0
0

Pełen tekst

(1)

Programowanie w języku C++

Programowanie w języku C++

Obiekty a zarządzanie pamięcią

Część siódma Roman Simiński roman.siminski@us.edu.pl www.us.edu.pl/~siminski Autor Kontakt

(2)

Pojęcie sterty

Pojęcie sterty ― heap― heap Sterta

Sterta (ang.heap) to wydzielony obszar pamięci:

przeznaczony do przechowywania danych dynamicznych,

kontrolowany ręcznie przez programistę,

ograniczony pod względem rozmiaru.

Typowy scenariusz wykorzystania sterty:

przydział niezbędnej w danym momencie ilości pamięci — najpóźniej jak to

możliwe,

wykorzystanie przydzielonego obszaru,

zwolnienie przydzielonej pamięci natychmiast, gdy nie jest już ona

potrzebna.

Rozmiar sterty zmienia się wraz ze zmianą środowiska systemowego i kompilatora. Zwykle jest on jednak wystarczający dla typowych programów. Jednak przetwarzanie grafiki czy danych multimedialnych może wymagać ustawień specyficznych.

(3)

Dynamiczny przydział pamięci w językach C i C++

Dynamiczny przydział pamięci w językach C i C++

Zarządzanie pamięcią przydzielaną dynamicznie w języku C

W języku C dynamiczny przydział pamięci realizowały funkcje:

void * malloc( size_t size ),

void * calloc( size_t nitems, size_t size ),

void * realloc( void * ptr, size_t size ).

Obszary pamięci przydzielone tymi funkcjami należało zwolnić funkcją:

void free( void * ptr ).

Zarządzanie pamięcią przydzielaną dynamicznie w języku C++

W języku C++ dynamiczny przydział pamięci realizować będzie:

operator new,

a zwalnianie przydzielonej pamięci:

operator delete.

(4)

Dynamiczny przydział pamięci w językach C i C++

Dynamiczny przydział pamięci w językach C i C++

Zarządzanie pamięcią przydzielaną dynamicznie w języku C

Funkcje przydzielające pamięć nie są częścią języka, pochodzą z biblioteki

zarządzania pamięcią.

Funkcje przedzielające pamięć traktowane są jako amorficzne bloki, o

liczonym w bajtach rozmiarze zdefiniowanym przez programistę.

Typ przdzielanych obszarów nie jest funkcją znany, programista musi

panować nad rozmiarami przydzielonych bloków.

Zarządzanie pamięcią przydzielaną dynamicznie w języku C++

Zarządzanie pamięcią zostało włączone języka, operatory new i delete są

znane kompilatorowi,

Stosowanie operatorów new i delete zapewnia aktywowanie konstruktorów

dla inicjalizacji tworzonych obieków oraz destruktorów dla czynności

(5)

Dynamiczny przydział pamięci w C++

Dynamiczny przydział pamięci w C++

Przydział pamięci dla obiektu klasy Square

Square * p; p = new Square; cout << p->getSide(); delete p;

Użycie operatora new powoduje przydzielenie pamięci dla obiektu w obszarze zwanym stertą, oraz inicjalizację tego obiektu z wykorzystaniem odpowiedniego konstruktora.

Utworzenie obiektu i inicjalizacja — wywołanie konstruktora bezparametrowego

Usunięcie obiektu i czynności kończące — wywołanie destruktora

Square * a = new Square; // Aktywowanie konstruktora domy lnegoś Square * b = new Square( 10 ); // Aktywowanie konstruktora ogólnego

Square * c = new Square( *b ); // Aktywowanie konstruktora kopiuj cegoą

Można sterować rodzajem inicjalizacji

Usuwanie obiektu operatorem delete

delete a; delete b; delete c;

(6)

Dynamiczny przydział pamięci w C++

Dynamiczny przydział pamięci w C++

Uwagi na temat zwalniania pamięci

Operator delete może być stosowany wyłącznie dla obiektów utworzonych operatorem new.

Mieszanie operatorów new i delete z funkcjami typu malloc i free daje niezdefiniowane rezultaty.

Jeżeli operator delete zostanie użyty dla wskaźnika zerowego, nic się nie stanie a operacja ta nie jest błędna.

Dwukrotne (lub wielokrotne) usunięcie tego samego obiektu jest błędem i prowadzi do problemów.

Uwaga — odwoływanie się do obszaru pamięci, który został wcześniej zwolniony jest błędem zarówno w C jak i w C++.

Square * p = new Square; . . .

delete p;

// To nie jest rozs dne: ą

p->setSide( 100 ); cout << p->getSide();

(7)

Dynamiczny przydział pamięci w C++

Dynamiczny przydział pamięci w C++

Uwagi na temat zwalniania pamięci

Dobrą praktyką jest zerowanie wskaźnika tuż po zwolnieniu pamięci,

Pozwala to na kontrolowanie czy można odwołać się do obiektu wskazywanego w innym miejscu programu.

Uwaga — w jęzuku C++ można zakładać, że wskaźnik pusty (pokazujący na nic) ma wartość zero. Korzystanie ze stałej NULL wymaga włączenia przynajmniej pliku nagłówkowego stddef.h.

Square * p = new Square; . . . delete p; p = 0; // Wersja 1-sza: if( p ) { p->setSide( 100 ); . . . } // Wersja 2-ga: if( p != 0 ) { p->setSide( 100 ); . . . } // Wersja 3-cia: if( p != NULL ) { p->setSide( 100 ); . . . } To jest rozsądne:

(8)

Dynamiczny przydział pamięci w C++

Dynamiczny przydział pamięci w C++

Przedział pamięci dla tablic obiektów

Operator new może być wykorzystany do utworzenia tablicy obiektów.

Stosowanie tego operatora zapewnia, że dla każdego elementu tablicy zostanie aktywowany konstruktor domyślny.

Square * sTab = new Square[ 10 ];

Tak utworzona tablica może być wykorzystana w normalny dla tablic sposób:

for( int i = 0; i < 10; i++ ) cout << sTab[ i ].getSide();

Taką tablicę należy jednak usunąć w specyficzny sposób:

delete [] sTab;

(9)

Dynamiczny przydział pamięci w C++

Dynamiczny przydział pamięci w C++

Dynamiczne tablice mogą mieć rozmiar określony zmienną

int numOfSquares;

cout << "Podaj liczbe kwadratow :"; cin >> numOfSquares;

Square * sTab = new Square[ numOfSquares ]; for( int i = 0; i < numOfSquares; i++ )

cout << sTab[ i ].getSide() << endl; delete [] sTab;

Operatory new i delete mogą być stosowane dla typów wbudowanych

int n;

cout << "Podaj liczbe elementow:"; cin >> n;

int * iTab = new int[ n ]; for( int i = 0; i < n; i++ ) cout << iTab[ i ] << endl; delete [] iTab;

(10)

Dynamiczny przydział pamięci w C++

Dynamiczny przydział pamięci w C++

Należy uważać na dynamicznie przydzielane obszary pamięci

int n;

cout << "Podaj liczbe elementow:"; cin >> n;

int * iTab = new int[ n ]; . . .

iTab = new int[ 10 ]; // Poprzednio przydzielony obszar został utracony . . .

for( int i = 0; i < n; i++ ) cout << iTab[ i ] << endl; delete [] iTab;

Można temu częściowo zaradzić

int * const iTab = new int[ n ];

(11)

Dynamiczny przydział pamięci w C++

Dynamiczny przydział pamięci w C++

Przydział pamięci dla tablic wielowymiarowych

const int MAX_LINE_LEN = 256; int numOfLines;

char ( * lines )[ MAX_LINE_LEN ];

cout << "Podaj liczbe linii: "; cin >> numOfLines;

lines = new char[ numOfLines ][ MAX_LINE_LEN ];

for( int i = 0; i < numOfLines; i++ ) {

sprintf( lines[ i ], "Linia nr: %-2d", i + 1 ); cout << endl << lines[ i ];

}

delete [] lines;

Przy alokacji tablic wielowymiarowych wszystkie wymiary poza pierwszym muszą być nieujemnymi wyrażeniami o wartości znanej na etapie kompilacji. Wymiar pierwszy może być zadany zmienną.

(12)

Dynamiczny przydział pamięci w C++

Dynamiczny przydział pamięci w C++

Gdy pamięci jest za mało...

void out_of_memory() {

cerr << "Brak pami ci";ę exit( EXIT_FAILURE ); }

Jeżeli operator new nie potrafi znaleźć ciągłego, wolnego obszaru pamięci dla obiektu: sprawdza czy programista zdefiniował specjalną funkcję obsługi takiej sytuacji, jeżeli taka funkcja istnieje, jest ona wywoływana,

w przeciwnym wypadku generowany jest wyjątek, dawniej rezultatem operatora była wartość zero.

Programista definiuje własną funkcję obsługi braku pamięci wykorzystując funkcję

set_new_handler()

zdefiniowaną w pliku nagłówkowym new.h.

(13)

Dynamiczny przydział pamięci w C++

Dynamiczny przydział pamięci w C++

Czy to działa ― sprawdź kiedy skończy się pamięć

#include <iostream> #include <cstdlib> #include <new> using namespace std; void out_of_memory() {

cerr << "Brak pami ci";ę exit( EXIT_FAILURE ); } int main() { set_new_handler( out_of_memory ); for(;;) new int[ 100000 ]; return EXIT_SUCCESS; }

Cytaty

Powiązane dokumenty

Przyszedł wiceprezydent miasta oraz były wiceprezydent, który witał wagon 5 lat temu, podczas pierwszego przejazdu oraz, co dla nas bardzo ważne, ludzie, którzy

- Niekoniecznie, w zespole powstał sprze- ciw, Jak ma się przed oczami ruinę, która sta- wała się już pijacką meliną, rozsypujące się ściany, tynk opadający na głowy, kiedy

Dynamiczny przydział pamięci na macierz Dynamiczne struktury danych.. stos, kolejka,

Dynamiczny przydział pamięci Dynamiczny przydział pamięci Dynamiczne struktury danych... Tablice o zmiennym rozmiarze (VLA) Tablice o zmiennym

Edelman omawia sposób i zasady funkcjonowania somatycznych systemów selekcyjnych na przykładzie układu odpornościowego, którym zajmował się przez wiele lat jako immunolog

[r]

Kolejnym elementem wyposażenia, na któ- rym pod żadnym pozorem nie wolno oszczę- dzać, jest zapasowe źródło zasilania. Jego brak zawsze okaże się bardzo bolesny i

formy udostępnienia dokumentacji medycznej ze szczególnym uwzględnie- niem udostępniania oryginału tej dokumentacji, możliwość pobierania opłat za udostępnienie