Upload
others
View
7
Download
0
Embed Size (px)
Citation preview
Allocazione dinamica di memoria in C++
Corso di programmazione I AA 2019/20
Corso di Laurea Triennale in Informatica
Prof. Giovanni Maria Farinella
Web: http://www.dmi.unict.it/farinella
Email: [email protected]
Dipartimento di Matematica e Informatica
Allocazione dinamica: Heap o Free Store
Lo heap e un altro segmento di memoria adibito ai dati che
vengono allocati dinamicamente.
...
...Record di
attivazione per lafunzione main()(variabili locali,
parametri attuali)
Record diattivazione per la
funzione foo()(variabili locali,
parametri attuali,indirizzo di ritorno)
Segmento STACK
ab...
xreturn addr.
cd
...
...
Variabili allocate
dinamicamente
HEAP
...
Allocazione automatica Allocazione dinamica
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 1
Allocazione: operatore new del C++
1 i n t ∗a = new i n t ;
2 f l o a t ∗ f = new f l o a t ( 0 . 9 ) ;
3 ∗a = 1 0 ;
4 double ∗ a r r = new double [ 1 0 ] ;
L’operatore new permette di operare allocazione dinamica.
Il segmento di memoria per allocazione dinamica e denominato
Heap o free store.
Per istanziare un oggetto, per ospitare un array o una singola
variabile di un determinato tipo.
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 2
Deallocazione: operatore delete
A differenza della allocazione automatica (stack), la memoria
allocata dinamicamente va successivamente liberata
mediante l’operatore delete
1 i n t ∗a = new i n t ;
2 // . . .
3 d e l e t e a ; // d e a l l o c a z i o n e
deallocazione di un blocco di memoria
1 double ∗ a r r = new double [ 1 0 ] ;
2 // . .
3 d e l e t e [ ] a r r ;
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 3
Deallocazione: operatore delete
Il valore del puntatore (indirizzo di memoria) rimane invariato!
Si provi:
1 i n t ∗a = new i n t ;
2 double ∗ a r r = new double [ 1 0 ] ;
3 cout << a r r << end l ; // 0 xaabb1244
4 // . . .
5 d e l e t e a ; // d e a l l o c a z i o n e
6 // . .
7 d e l e t e [ ] a r r ;
8 cout << a r r << end l ; //0 xaabb1244
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 4
Memory leak
1 double ∗ a r r = new double [ 1 0 ] ;
2 // . .
3 double ∗v = new double [ 1 5 ] ;
4 // . .
5 v = a r r ;
A seguito della copia di un differente indirizzo di memoria nella variabile
v (“effetto aliasing”), si perde il riferimento (indirizzo) al blocco di
memoria di 15 elementi double.
Deallocare il blocco di memoria con l’operatore delete ? Non piu
possibile!
Puo essere un problema, ad esempio un Web server (centinaia di gg di
uptime!)
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 5
Double Deletion
1 double ∗ a r r = new double [ 1 0 ] ;
2 // . .
3 d e l e t e [ ] a r r ;
4 // . .
5 d e l e t e [ ] a r r ;
Puo capitare, soprattutto in un programma lungo e complesso di operare,
per errore, una doppia delete.
Cosa succede alla riga 5? Come gia detto in precedenza, il valore del
puntatore, dopo la delete, rimane invariato.
Il tentativo di deallocazione avra un comportamento indefinito, ovvero
non predicibile e possibilmente disastroso.
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 6
Double Deletion
1 double ∗ a r r = new double [ 1 0 ] ;
2 // . .
3 i f ( a r r ){4 d e l e t e [ ] a r r ;
5 a r r = n u l l p t r ;
6 }7 // . . a l t r i t e n t a t i v i d i d e a l l o c a z i o n e
Buona norma, ad ogni tentativo di deallocazione
• inserire un controllo sul valore del puntatore
• “azzerare” il puntatore dopo la delete
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 7
Premature deletion
1 double ∗ a r r = new double [ 1 0 ] ;
2 // . .
3 double ∗v = a r r ;
4 // . .
5 i f ( a r r ){6 d e l e t e [ ] a r r ;
7 a r r = n u l l p t r ;
8 }9 // . .
10 v [ 5 ] = 4 . 56789 ; // ! ! !
Dopo la delete di arr, operata per errore, esso sara nullptr, ma v
conserva il vecchio valore di arr!!
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 8
Funzioni che restituiscono un puntatore
1 i n t ∗ f unc ( i n t k ){2 i n t a r r [ k ] ;
3 f o r ( i n t i =0; i<k ; i++)
4 a r r [ k ] = 2∗k ;5 r e t u r n a r r ;
6 }7
8 i n t ∗ a r r a y = func ( 1 0 ) ;
Corretto? .. NO!
Infatti arr allocato automaticamente nello stack. Dobbiamo
ricordare cosa accade dopo l’istruzione return al record di
attivazione dello stack della funzione..
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 9
Funzioni che restituiscono un puntatore
1 i n t ∗ f unc ( i n t k ){2 i n t ∗ a r r = new i n t [ k ] ;
3 f o r ( i n t i =0; i<k ; i++)
4 a r r [ k ] = 2∗k ;5 r e t u r n a r r ;
6 }7
8 i n t ∗ a r r a y = func ( 1 0 ) ;
Corretto? .. SI!
arr allocato dinamicamente nel free store.
Memoria allocata per arr nel free store non sara liberata fino a
chiamata delete [].
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 10
Allocazione dinamica in C: malloc() e free()
1 #i n c l u d e <c s t d l i b >
2 double ∗ a r r = ( double ∗) malloc( s i z e o f ( double ) ∗ 10 ) ;
3 // . .
4 free(arr) ; // d e a l l o c a z i o n e
malloc() alloca dinamicamente un blocco di memoria:
• argomento e dimensione in byte (importante l’uso di sizeof:
portabilita!)
• restituisce un puntatore generico, ovvero di tipo void *, per
questo bisogna operare un type casting al tipo desiderato.
La funzione free() libera la memoria precedentemente allocata,
come delete in C++.
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 11
Allocazione dinamica di un array multidimensionale
1 #d e f i n e COLS 10
2 #d e f i n e ROWS 5
3 double ∗ a r r [ROWS] ;
4 // oppure
5 double ∗∗ a r r = new double ∗ [ROWS] ;
6 f o r ( i n t i =0; i<ROWS; i ++)
7 a r r [ i ]=new double [ COLS ] ;
1. Allocazione automatica (nello stack, linea 3) o dinamica (free
store/heap, linea 5) di un vettore di (ROWS) puntatori a tipo double.
2. Allocazione dinamica di ROWS vettori di COLS celle di tipo
double.
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 12
Allocazione dinamica di un array multidimensionale
0xaabb11
0x...
a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] ... ... a[0][M]
int *a[N] 0x445566 0x44556a ...
a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] ... ... a[1][M]
...
N x M
Stack ofree store Free store
a[0]
a[1]
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 13
Allocazione dinamica di un array multidimensionale
1 double ∗ a r r [ROWS] ;
2 // oppure
3 double ∗∗ a r r = new double ∗ [ROWS] ;
4 f o r ( i n t i =0; i<ROWS; i ++)
5 a r r [ i ]=new double [ COLS ] ;
Accesso agli elementi (NB linea 3)
1 a r r [ i ] [ j ] ;
2 (∗ ( a r r+i ) ) [ j ] ;
3 *(arr+i)[j] ; //NO: ==∗( a r r+i+j )==a r r [ i+j ] [ 0 ]
4 ∗( a r r [ i ] + j ) ;
5 ∗ (∗ ( a r r+i ) + j ) ;
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 14
FINE
Prof. Giovanni Maria Farinella DMI UNICT [PDF generato il 12 novembre 2020 alle ore 03:46] 15