Allocazione dinamica di memoria in C++
Corso di programmazione I (A-L) AA 2019/20
Corso di Laurea Triennale in Informatica
Fabrizio Messina
messina@[Link]
Dipartimento di Matematica e Informatica
Allocazione dinamica: Heap o Free Store
Lo heap è un altro segmento di memoria adibito ai dati che
vengono allocati dinamicamente.
Segmento STACK HEAP
... Record di ...
attivazione per la
funzione foo()
(variabili locali, Variabili
d
c parametri attuali, allocate
x indirizzo di ritorno) dinamicamente
return addr.
... ...
Record di
attivazione per la
funzione main()
... (variabili locali, ...
b parametri attuali)
a
Allocazione automatica Allocazione dinamica
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 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 = 10;
4 double ∗ a r r = new double [ 1 0 ] ;
L’operatore new permette di operare allocazione dinamica.
Il segmento di memoria per allocazione dinamica è denominato
Heap o free store.
Per istanziare un oggetto, per ospitare un array o una singola
variabile di un determinato tipo.
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 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 doubl e ∗ a r r = new double [ 1 0 ] ;
2 // . .
3 delete [ ] arr ;
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 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 doubl e ∗ a r r = new double [ 1 0 ] ;
3 c o u t << a r r << e n d 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 delete [ ] arr ;
8 c o u t << a r r << e n d l ; // 0 xaabb1244
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 4
Memory leak
1 doubl e ∗ a r r = new double [ 1 0 ] ;
2 // . .
3 doubl e ∗ v = new double [ 1 5 ] ;
4 // . .
5 v = arr ;
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 più
possibile!
Può essere un problema, ad esempio un Web server (centinaia di gg di
uptime!)
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 5
Double Deletion
1 doubl e ∗ a r r = new double [ 1 0 ] ;
2 // . .
3 delete [ ] arr ;
4 // . .
5 delete [ ] arr ;
Può capitare, soprattutto in un programma lungo e complesso di operare,
per errore, una doppia delete.
Cosa succede alla riga 5? Come già detto in precedenza, il valore del
puntatore, dopo la delete, rimane invariato.
Il tentativo di deallocazione avrà un comportamento indefinito, ovvero
non predicibile e possibilmente disastroso.
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 6
Double Deletion
1 doubl e ∗ a r r = new double [ 1 0 ] ;
2 // . .
3 i f ( a r r ){
4 delete [ ] arr ;
5 arr = nullptr ;
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
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 7
Premature deletion
1 doubl e ∗ a r r = new double [ 1 0 ] ;
2 // . .
3 doubl e ∗ v = a r r ;
4 // . .
5 i f ( a r r ){
6 delete [ ] arr ;
7 arr = nullptr ;
8 }
9 // . .
10 v [ 5 ] = 4 . 5 6 7 8 9 ; // ! ! !
Dopo la delete di arr, operata per errore, esso sarà nullptr, ma v
conserva il vecchio valore di arr!!
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 8
Funzioni che restituiscono un puntatore
1 i n t ∗ func ( i n t k ){
2 int arr [ k ] ;
3 f o r ( i n t i =0; i <k ; i ++)
4 a r r [ k ] = 2∗ k ;
5 return arr ;
6 }
7
8 int ∗ array = func (10);
Corretto? .. NO!
Infatti arr allocato automaticamente nello stack. Dobbiamo
ricordare cosa accade dopo l’istruzione return al record di
attivazione dello stack della funzione..
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 9
Funzioni che restituiscono un puntatore
1 i n t ∗ func ( 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 return arr ;
6 }
7
8 int ∗ array = func (10);
Corretto? .. SI!
arr allocato dinamicamente nel free store.
Memoria allocata per arr nel free store non sarà liberata fino a
chiamata delete [].
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 10
Allocazione dinamica in C: malloc() e free()
1 #i n c l u d e < c s t d l i b >
2 doubl e ∗ a r r = ( double ∗ ) malloc ( s i z e o f ( double ) ∗ 1 0 ) ;
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 è dimensione in byte (importante l’uso di sizeof:
portabilità!)
• 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++.
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 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 // o p p u r e
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.
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 12
Allocazione dinamica di un array multidimensionale
int *a[N] 0x445566 0x44556a ...
a[0] 0xaabb11 a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] ... ... a[0][M]
...
a[1] 0x... a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] ... ... a[1][M]
NxM
Stack o
Free store
free store
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 13
Allocazione dinamica di un array multidimensionale
1 double ∗ a r r [ROWS ] ;
2 // o p p u r e
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 arr [ 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 ) ;
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 14
Esempi svolti
Esempi
19 [Link]
19 [Link]
19 [Link]
19 [Link]
19 [Link]
19 [Link]
Fabrizio Messina DMI Unict [PDF generato il 5 novembre 2019 alle ore 09:38] 15