G. Amodeo,
C. Gaibisso
Programmazione di Calcolatori
Lezione XVI
Allocazione dinamica della
memoria
Programmazione di Calcolatori: allocazione dinamica della memoria
1
G. Amodeo,
C. Gaibisso
Operatore sizeof()
• Buffer:
in questa lezione per buffer intenderemo una
sequenza contigua di byte (locazioni) in
memoria centrale
• Sintassi:
sizeof(tipo_di_dato)
con tipo_di_dato identificatore di tipo
predefinito o non
• Valore:
numero di byte utilizzati per rappresentare
un valore di tipo tipo_di_dato
Programmazione di Calcolatori: allocazione dinamica della memoria
2
G. Amodeo,
C. Gaibisso
Operatore di casting
• Sintassi:
(tipo_di_dato) espressione
con tipo_di_dato identificatore
di tipo predefinito o non
• Valore:
il valore di espressione
convertito in un valore di tipo
tipo_di_dato
Programmazione di Calcolatori: allocazione dinamica della memoria
3
G. Amodeo,
C. Gaibisso
Il tipo size_t
• Definizione:
typedef unsigned int size_t;
utilizzato per rappresentare dimensioni
• Range di rappresentazione:
tra 0 e 2
sizeof(size_t)*8
-1
Programmazione di Calcolatori: allocazione dinamica della memoria
4
G. Amodeo,
C. Gaibisso
Direttiva per il preprocessore
Attenzione!!!
Le librerie del C mettono a disposizione del
programmatore un insieme di funzioni per la
gestione della memoria. Per utilizzare tali
funzioni all’interno di un file è necessario
includere in testa allo stesso la direttiva per il
preprocessore:
# include <stdlib.h>
Programmazione di Calcolatori: allocazione dinamica della memoria
5
G. Amodeo,
C. Gaibisso
La funzione malloc()
• Signature (firma):
void *malloc(size_t size);
• Modifiche allo stato della memoria:
alloca un buffer di memoria di size byte
• Valore restituito:
- l’indirizzo del primo byte del buffer, in
caso di successo
- il valore NULL altrimenti
Programmazione di Calcolatori: allocazione dinamica della memoria
6
G. Amodeo,
C. Gaibisso
La funzione free()
• Signature:
void free(void *ptr);
• Modifiche allo stato della memoria:
rilascia il buffer di memoria, di indirizzo
iniziale ptr, allocato da una precedente
chiamata alla malloc(), calloc() o
realloc()
Programmazione di Calcolatori: allocazione dinamica della memoria
7
G. Amodeo,
C. Gaibisso
Le funzioni malloc() e free()
// sorgente: Lezione_XVI\malloc.c
// illustra il corretto utilizzo dalla funzione malloc() e della free()
// inclusione del file di intestazione della libreria standard che
// contiene definizioni di macro, costanti e dichiarazioni di funzioni
// e tipi funzionali alle varie operazioni di I/O
#include <stdio.h>
// inclusione del file di intestazione della libreria standard che
// contiene definizioni di macro, costanti e dichiarazioni di funzioni
// di interesse generale
#include <stdlib.h>
// visualizza il contenuto di un buffer di interi
void VisBuffInt(int *ptr, size_t nro_val)
{
// definisce la variabile necessaria a muoversi sul buffer
size_t curs;
// attraversa il buffer visualizzandone il contenuto
for (curs = 0; curs <= dim-1; curs++)
printf("\n%d", ptr[curs]);
};
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
8
G. Amodeo,
C. Gaibisso
Le funzioni malloc() e free()
continua …
// alloca, visualizza e successivamente rilascia, buffer per
// un numero di valori interi specificato a run-time
int main()
{
// definisce le variabili per il numero dei valori interi e per
// l’indirizzo iniziale del buffer
size_t nro_val;
int *ptr;
// inizializza la variabile per il numero di valori
printf("\nQuanti valori? ");
scanf("%u", &nro_val);
// alloca memoria per il buffer
ptr = (int*) malloc(nro_val * sizeof(int));
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
9
G. Amodeo,
C. Gaibisso
Le funzioni malloc() e free()
continua …
// se l’allocazione e’ fallita termina
if (ptr == NULL)
{
printf("\nAllocazione fallita");
return(0);
};
// se l'allocazione è avvenuta con successo visualizza il contenuto
// del buffer e rilascia la memoria per questo allocata
printf("\nAllocazione avvenuta con successo\n");
printf(“\nContenuto del buffer: “);
VisBuffInt(ptr, nro_val);
free(ptr);
return(1);
}
Programmazione di Calcolatori: allocazione dinamica della memoria
10
G. Amodeo,
C. Gaibisso
Le funzioni malloc() e free()
• Compilazione:
• Esecuzione:
Il buffer non
viene
inizializzato
• Esecuzione:
Programmazione di Calcolatori: allocazione dinamica della memoria
11
G. Amodeo,
C. Gaibisso
La funzione calloc()
• Signature:
void *calloc(size_t nro_var, size_t dim_var);
• Modifiche allo stato della memoria:
alloca un buffer di memoria per nro_var
variabili di dimensione dim_var, e le inizializza
a0
• Valore restituito:
- l’indirizzo del primo byte del buffer, in caso di
successo
- il valore NULL altrimenti
Programmazione di Calcolatori: allocazione dinamica della memoria
12
G. Amodeo,
C. Gaibisso
Le funzioni calloc() e free()
// sorgente: Lezione_XVI\calloc.c
// illustra il corretto utilizzo dalla funzione calloc() e della free()
// inclusione del file di intestazione della libreria standard che
// contiene definizioni di macro, costanti e dichiarazioni di funzioni
// e tipi funzionali alle varie operazioni di I/O
#include <stdio.h>
// inclusione del file di intestazione della libreria standard che
// contiene definizioni di macro, costanti e dichiarazioni di funzioni
// di interesse generale
#include <stdlib.h>
// visualizza il contenuto di un buffer di interi
void VisBuffInt(int *ptr, size_t dim)
{
// definisce la variabile necessaria a muoversi sul buffer
size_t curs;
// attraversa il buffer visualizzandone il contenuto
for (curs = 0; curs <= dim-1; curs++)
printf("\n%d", ptr[curs]);
};
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
13
G. Amodeo,
C. Gaibisso
Le funzioni calloc() e free()
continua …
// alloca, visualizza e successivamente rilascia, un buffer per
// un numero di valori interi specificato a run-time
int main()
{
// definisce le variabili per il numero dei valori interi e per
// l’indirizzo iniziale del buffer
size_t nro_val;
int *ptr;
// inizializza la variabile per il numero di valori
printf("\nQuanti valori? ");
scanf("%u", &nro_val);
// alloca e inizializza la memoria per il buffer
ptr = (int*) calloc(nro_val, sizeof(int));
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
14
G. Amodeo,
C. Gaibisso
Le funzioni calloc() e free()
continua …
// se l’allocazione e’ fallita termina
if (ptr == NULL)
{
printf("\nAllocazione fallita");
return(0)
};
// se l'allocazione ha avuto successo visualizza il contenuto del
// buffer e successivamente libera la memoria per questo allocata
printf("\nAllocazione avvenuta con successo\n");
printf("\nContenuto del buffer:");
VisBuffIn(ptr, nro_val);
free(ptr);
return(1);
}
Programmazione di Calcolatori: allocazione dinamica della memoria
15
G. Amodeo,
C. Gaibisso
Le funzioni calloc() e free()
• Compilazione:
• Esecuzione:
Il buffer è
inizializzato a 0
• Esecuzione:
Programmazione di Calcolatori: allocazione dinamica della memoria
16
G. Amodeo,
C. Gaibisso
La funzione realloc()
• Signature:
void *realloc(void * ptr, size_t size);
• Modifiche allo stato della memoria:
estende, o nel caso comprime, il buffer riferito
da ptr, mantenendo inalterato il contenuto
della porzione preesistente, a meno di
troncamenti. Gestisce automaticamente
eventuali ricollocazioni del buffer.
• Valore restituito:
- l’indirizzo del primo byte del buffer, in caso di
successo
- il valore NULL altrimenti
• Realloc(NULL, size):
equivale a malloc(size)
Programmazione di Calcolatori: allocazione dinamica della memoria
17
G. Amodeo,
C. Gaibisso
La funzione realloc() e i memory leak
• Memory leak:
area di memoria allocata e non più
accessibile non esistendo puntatori che
la riferiscono
void *ptr = realloc(NULL, 5);
ptr = realloc(ptr, 8);
…
NULL
free(ptr);
Non ha alcun effetto
100
NULL
ptr
099
100
101
102
103
104
105
Programmazione di Calcolatori: i vettori
x
x
x
x
x
18
G. Amodeo,
C. Gaibisso
La funzione realloc()
• L’approccio corretto:
void *ptr , *tmp;
ptr = realloc(NULL, 2);
tmp = realloc(ptr, 4);
// gestione dell’errore
if (tmp == NULL)
{
printf (“errore”);
free(ptr);
return (0);
}
else
ptr = tmp;
….
free(ptr);
100
103
ptr
103
tmp
099
100
101
102
103
104
105
106
107
Programmazione di Calcolatori: i vettori
x
x
x
x
x
x
x
x
19
G. Amodeo,
C. Gaibisso
La funzione realloc()
// sorgente: Lezione_XVI\realloc.c
// illustra il corretto utilizzo dalla funzione realloc()
// inclusione del file di intestazione della libreria standard che
// contiene definizioni di macro, costanti e dichiarazioni di funzioni
// e tipi funzionali alle varie operazioni di I/O
#include <stdio.h>
// inclusione del file di intestazione della libreria standard che
// contiene definizioni di macro, costanti e dichiarazioni di funzioni
// di interesse generale
#include <stdlib.h>
// inizializza il contenuto di un buffer di interi con una sequenza
// progressiva di interi
void InBuffInt(int *ptr, size_t dim)
{
// definisce la variabile necessaria a muoversi sul buffer
size_t curs;
// attraversa il buffer visualizzandone il contenuto
for (curs = 0; curs <= dim-1; curs++)
ptr[curs] = curs;
};
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
20
G. Amodeo,
C. Gaibisso
La funzione realloc()
continua …
// visualizza il contenuto di un buffer di interi
void VisBuffInt(int *ptr, size_t dim)
{
// definisce la variabile necessaria a muoversi sul buffer
size_t curs;
// attraversa il buffer visualizzandone il contenuto
for (curs = 0; curs <= dim-1; curs++)
printf("\n%d", ptr[curs]);
};
// alloca, visualizza, ridimensiona, visualizza nuovamente e rilascia, un
// buffer per un numero di valori interi specificato a run-time
int main()
{
// definisce le variabili per il numero dei valori interi e per
// il riferimento al buffer iniziale
size_t nro_val;
int *ptr;
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
21
G. Amodeo,
C. Gaibisso
La funzione realloc()
continua …
// definisce una variabile temporanea per il riferimento al buffer
// ridimensionato, al fine di non perdere il riferimento al buffer
// iniziale se il ridimensionamento fallisse
int *tmp;
// definisce una variabile per il numero di valori interi nel buffer
// ridimensionato
size_t new_nro_val;
// inizializza la variabile per il numero di valori nel buffer iniziale
printf("\nQuanti valori nel buffer iniziale? ");
scanf("%u", &nro_val);
// alloca memoria per il buffer iniziale
ptr = (int *) realloc(NULL, nro_val*sizeof(int));
// se l’allocazione è fallita termina
if (ptr == NULL)
{
printf("\nAllocazione fallita");
return(0);
};
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
22
G. Amodeo,
C. Gaibisso
La funzione realloc()
continua …
// altrimenti, se l'allocazione ha avuto successo, inizializza e
// visualizza il buffer iniziale
printf("\nAllocazione avvenuta con successo\n");
InBuffInt(ptr, nro_val);
printf("\nBuffer iniziale:\n");
VisBuffInt(ptr, nro_val);
// inizializza la variabile per il numero di valori nel buffer
// ridimensionato
printf("\nQuanti valori nel buffer ridimensionato? ");
scanf("%u", &new_nro_val);
// ridimensiona il buffer iniziale
tmp = (int *)realloc(ptr, new_nro_val);
// verifica se il ridimensionamento è avvenuto con successo
if (tmp == NULL)
{
// se il ridimensionamento e' fallito visualizza il buffer originale
// e termina
printf("\nAllocazione fallita”);
printf("\nBuffer iniziale:\n ");
VisBuffInt(ptr, nro_val);
};
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
23
G. Amodeo,
C. Gaibisso
La funzione realloc()
continua …
// se il ridimensionamento e’ avvenuto con successo
// aggiorna il riferimento al buffer
ptr = tmp;
// visualizza il contenuto del buffer ridimensionato
printf("\nAllocazione avvenuta con successo”);
printf("\nBuffer ridimensionato:");
VisBuffInt(ptr, new_nro_val);
// rilascia la memoria allocata per il buffer
free(ptr);
return(1);
}
Programmazione di Calcolatori: allocazione dinamica della memoria
24
G. Amodeo,
C. Gaibisso
La funzione realloc()
• Compilazione:
• Esecuzione:
Programmazione di Calcolatori: allocazione dinamica della memoria
25
G. Amodeo,
C. Gaibisso
La funzione realloc() e free()
• Esecuzione:
Programmazione di Calcolatori: allocazione dinamica della memoria
26
G. Amodeo,
C. Gaibisso
Le funzioni calloc() e free()
• Esecuzione:
Programmazione di Calcolatori: allocazione dinamica della memoria
27
G. Amodeo,
C. Gaibisso
La funzione memcpy()
• Signature:
void * memcpy(void * dest, void * src, int n)
• Modifiche allo stato della memoria:
copia n byte dall’indirizzo src all’indirizzo dst
• Valore restituito:
l’indirizzo dest
• Direttive per il preprocessore:
includere la direttiva #include <string.h> per
utilizzare la funzione
Programmazione di Calcolatori: allocazione dinamica della memoria
28
G. Amodeo,
C. Gaibisso
La funzione memcpy()
// sorgente: Lezione_XVI\memcpy.c
// illustra il corretto utilizzo dalla funzione memcpy()
// inclusione del file di intestazione della libreria standard
// che contiene definizioni di macro, costanti e dichiarazioni
// di funzioni e tipi funzionali alle varie operazioni di I/O
#include <stdio.h>
// inclusione del file di intestazione della libreria standard che
// contiene definizioni di macro,costanti e dichiarazioni di funzioni di
// interesse generale, per la gestione della memoria e delle stringhe
#include <stdlib.h>
#include <string.h>
// inizializza il contenuto di un buffer di interi con una sequenza pro// gressiva di interi
void InBuffInt(int *ptr, size_t dim)
{
// definisce la variabile necessaria a muoversi sul buffer
size_t curs;
// attraversa il buffer visualizzandone il contenuto
for (curs = 0; curs <= dim-1; curs++)
ptr[curs] = curs;
};
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
29
G. Amodeo,
C. Gaibisso
La funzione memcpy()
continua …
// visualizza il contenuto di un buffer di interi
void VisBuffInt(int *ptr, size_t dim)
{
// definisce la variabile necessaria a muoversi sul buffer
size_t curs;
// attraversa il buffer visualizzandone il contenuto
for (curs = 0; curs <= dim-1; curs++)
printf("\n%d", ptr[curs]);
};
// alloca due buffer di interi, inizializza il I, lo visualizza e lo copia nel II.
// Visualizza il contenuto del II e rilascia tutta la memoria allocata
int main()
{
// definisce le variabili per il numero dei valori interi e per i
// riferimenti ai due buffer
size_t nro_val;
int *ptr_1, *ptr_2;
// inizializza la variabile per il numero di valori in entrambe i buffer
printf("\nQuanti valori nei buffer? ");
scanf("%u", &nro_val);
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
30
G. Amodeo,
C. Gaibisso
La funzione memcpy()
continua …
// alloca memoria per i due buffer
ptr_1 = (int *) realloc(NULL,nro_val*sizeof(int));
ptr_2 = (int *) realloc(NULL,nro_val*sizeof(int));
// controlla se l’allocazione è avvenuta con successo
if ((ptr_1 == NULL) || (ptr_2 == NULL))
{
// se l’allocazione è fallita rilascia la memoria allocata
// e termina
printf("\nAllocazione fallita");
if (ptr_1 != NULL)
free(ptr_1);
if (ptr_2 != NULL)
free(ptr_1);
return(0);
};
// altrimenti inizializza il I buffer e lo visualizza
printf("\nAllocazione avvenuta con successo\n");
InBuffInt(ptr_1, nro_val);
printf("\nContenuto I Buffer:");
VisBuffInt(ptr_1, nro_val);
continua …
Programmazione di Calcolatori: allocazione dinamica della memoria
31
G. Amodeo,
C. Gaibisso
La funzione memcpy()
continua …
// copia il I buffer nel II e lo visualizza
ptr_2 = memcpy(ptr_2, ptr_1, nro_val*sizeof(int));
printf("\nContenuto II Buffer:");
VisBuffInt(ptr_2, nro_val);
// rilascia la memoria per entrambe i buffer
free(ptr_1);
free(ptr_2);
return(1);
}
Programmazione di Calcolatori: allocazione dinamica della memoria
32
G. Amodeo,
C. Gaibisso
La funzione memcpy()
• Compilazione:
• Esecuzione:
Programmazione di Calcolatori: allocazione dinamica della memoria
33
G. Amodeo,
C. Gaibisso
La funzione memcpy()
• Esecuzione:
Programmazione di Calcolatori: allocazione dinamica della memoria
34
Scarica

La funzione realloc()