La gestione della memoria



Documenti analoghi
Allocazione dinamica della memoria - riepilogo

I puntatori e l allocazione dinamica di memoria

Le operazioni di allocazione e deallocazione sono a carico del sistema.

Programmazione. Laboratorio. Roberto Cordone DI - Università degli Studi di Milano

Gli array. Gli array. Gli array. Classi di memorizzazione per array. Inizializzazione esplicita degli array. Array e puntatori

La gestione della memoria dinamica Heap

puntatori Lab. Calc. AA 2007/08 1

Laboratorio di Calcolatori 1 Corso di Laurea in Fisica A.A. 2006/2007

Fondamenti di Informatica T. Linguaggio C: i puntatori

Funzioni in C. Violetta Lonati

Appunti tratti dal videocorso on-line di Algoritmi e Programmazione Avanzata By ALeXio

costruttori e distruttori

dall argomento argomento della malloc()

Fondamenti di Informatica e Laboratorio T-AB T-16 Progetti su più file. Funzioni come parametro. Parametri del main

Dynamic Linking. Introduzione Creazione di una libreria dinamica Uso di una libreria dinamica

Strutture. Strutture e Unioni. Definizione di strutture (2) Definizione di strutture (1)

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Introduzione alla programmazione in C

Università di Torino Facoltà di Scienze MFN Corso di Studi in Informatica. Programmazione I - corso B a.a prof.

Il tipo di dato astratto Pila

Gestione dei File in C

Lezione 9: Strutture e allocazione dinamica della memoria

Oggetti Lezione 3. aspetti generali e definizione di classi I

VARIABILI LOCALI E GLOBALI (ESTERNE)

Gestione della memoria centrale

Inizializzazione, Assegnamento e Distruzione di Classi

Introduzione al linguaggio C Gli array

Indirizzo di una funzione. Puntatori a funzioni. Definizione di variabili. Definizione di variabili

Quotazione compareto( ) Quotazione piurecente( ) Quotazione Quotazione Quotazione non trovato count( )

Fondamenti di Informatica T-1, 2009/2010 Modulo 2 Prova d Esame 5 di Giovedì 15 Luglio 2010 tempo a disposizione 2h30'

GESTIONE INFORMATICA DEI DATI AZIENDALI

3 - Variabili. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

13 - Gestione della Memoria nella Programmazione Orientata agli Oggetti

Concetto di Funzione e Procedura METODI in Java

Linguaggio C - Stringhe

Breve riepilogo della puntata precedente:

Gestione Risorse Umane Web

I/O su Socket TCP: read()

2. Spiegare brevemente qual è la funzione del compilatore e la sua importanza per il programmatore.

AXO. Operativo. Architetture dei Calcolatori e Sistema. programmazione di sistema

Programmazione I / Informatica generale Prova scritta 11 Giugno 2008

Allocazione dinamica della memoria

Esercizio: gestione di un conto corrente

Sistema operativo: Gestione della memoria

Gestione dinamica della memoria

Realizzazione di Politiche di Gestione delle Risorse: i Semafori Privati

Le variabili. Olga Scotti

Laboratorio di Programmazione 1. Docente: dr. Damiano Macedonio Lezione 18 31/03/2014

Una funzione è detta ricorsiva se chiama, direttamente o indirettamente, se stessa. In C tutte le funzioni possono essere usate ricorsivamente.

Le funzioni in C. I programmi C sono costituiti da definizioni di variabili e funzioni.

Il memory manager. Gestione della memoria centrale

Variabili e tipi di dato

Java: Compilatore e Interprete

Corso di Fondamenti di Informatica

INFORMATICA 1 L. Mezzalira

Implementazione di Liste puntate

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Laboratorio di programmazione

Il linguaggio C. Puntatori e dintorni


Introduzione al Linguaggio C

Università degli Studi di Cassino Corso di Fondamenti di Informatica Puntatori. Anno Accademico 2010/2011 Francesco Tortorella

Algebra di Boole: Concetti di base. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica

La struttura dati ad albero binario

Programmazione C Massimo Callisto De Donato massimo.callisto@unicam.it

Funzioni. Il modello console. Interfaccia in modalità console

Homework HWC1 di Programmazione Concorrente 13 novembre 2014 anno accademico 2014/2015

Struttura a record. File ad accesso diretto. Modalità di apertura. Modalità di apertura

Le stringhe. Le stringhe

Appello di Informatica B

Elementi di Architettura e Sistemi Operativi

Capitolo Quarto...2 Le direttive di assemblaggio di ASM Premessa Program Location Counter e direttiva ORG

Tipi di Dato Ricorsivi

L'Allocazione Dinamica della Memoria nel linguaggio C

2. I THREAD. 2.1 Introduzione

Laboratorio di Algoritmi e Strutture Dati

Gestione dei File. dischi nastri cd

Verifica che una grammatica sia Context Free nel GrammaReader

LINGUAGGI DI PROGRAMMAZIONE

Sistemi Operativi (M. Cesati)

Aritmetica dei puntatori

Lab. di Sistemi Operativi - Esercitazione n 9- -Thread-

Riferimenti ed Oggetti

Programmazione ad Oggetti. Java Parte I

Esempio: dest = parolagigante, lettere = PROVA dest (dopo l'invocazione di tipo pari ) = pprrlogvgante

Arduino: Programmazione

Makefile. Un target in generale e' un file. Usando.PHONY: target specifichiamo a make che il target non e' un file

Il software. la parte contro cui si può solo imprecare. Funzioni principali del sistema operativo. (continua) Gestione della memoria principale

Programmare in Java. Olga Scotti

La selezione binaria

FONDAMENTI di INFORMATICA L. Mezzalira

Il Software. Il software del PC. Il BIOS

Matlab: Gestione avanzata dei file

La Gestione delle risorse Renato Agati

4. Un ambiente di sviluppo per Java

Corso di Sistemi di Elaborazione delle informazioni

Gestione della Memoria

Gian Luca Marcialis studio degli algoritmi programma linguaggi LINGUAGGIO C

Transcript:

La gestione della memoria DOTT. ING. LEONARDO RIGUTINI DIPARTIMENTO INGEGNERIA DELL INFORMAZIONE UNIVERSITÀ DI SIENA VIA ROMA 56 53100 SIENA UFF. 0577234850-7102 RIGUTINI@DII.UNISI.IT HTTP://WWW.DII.UNISI.IT/~RIGUTINI/

Le gestione della memoria Il C è, per natura, un linguaggio molto flessibile, e la sua gestione della memoria contribuisce a renderlo ancora più flessibile. A differenza di altri linguaggi (come il C++ o il Java), il C permette di assegnare la giusta quantità di memoria (solo e solamente quella necessaria) alle variabili del programma. Utilizzare queste caratteristiche del C permette di creare programmi altamente portabili, in quanto utilizzano di volta in volta i valori giusti per la piattaforma.

La gestione della memoria la memoria è divisa sostanzialmente in due parti: - una statica, che contiene tutto quello che sappiamo verrà allocato (come una variabile int, una struttura definita con struct ecc ) e che si chiama Stack, - una dinamica, cioè in cui la dimensione di memoria per rappresentare qualche elemento del programma può cambiare durante l'esecuzione del programma, che si chiama Heap.

La gestione della memoria: lo Heap Lo Heap è un lotto di memoria assegnato ad un processo specifico, per immagazzinare strutture dati, la cui esistenza o dimensione non possa essere determinata prima che il programma sia eseguito. Quando sono richiesti blocchi di memoria nello heap è necessario utilizzare una apposita funzione per allocare memoria. Una volta finito di utilizzare lo spazio ottenuto è necessario liberare la memoria allocata con un altra funzione (memoria dinamica). Se necessario è possibile chiedere blocchi aggiuntivi nello heap utilizzando un altra apposita funzione. La memoria nello Heap si può accedere solamente attraverso un puntatore o una catena di puntatori allocati nello Stack.

La gestione della memoria: lo Heap Lo heap è gestito dal S.O. in paragrafi minimi (di 16, 32 o 64 byte): - la richiesta di un certo quantitativo di memoria viene arrotondato per eccesso al multiplo successivo del paragrafo minimo; - inoltre, viene generalmente aggiunto un paragrafo per informazioni accessorie.

La gestione della memoria: lo Heap L uso continuo di allocazione e rilascio di memoria heap causa un frazionamento dello spazio disponibile con conseguente peggioramento delle prestazioni: solo alcuni S.O. possono deframmentare lo spazio, ridisponendo tutti i blocchi. Il programmatore deve attentamente valutare costi e benefici della gestione Heap, sostituendola quando possibile con un assegnazione iniziale di tutto lo spazio necessario, o con la creazione dinamica di spazio sullo Stack.

La gestione della memoria Le funzioni utilizzate per gestire la memoria dinamica sono principalmente quattro: - malloc() e calloc() adibite all'allocazione della memoria, - free() che, come si intuisce, serve per liberare la memoria allocata, - realloc() la cui funzione è quella di permettere la modifica di uno spazio di memoria precedentemente allocato. Un comando particolarmente utile risulta essere sizeof, che restituisce la dimensione del tipo di dato da allocare. Queste funzioni sono disponibili nella standard library: in particolare è necessario includere il file malloc.h

La gestione della memoria E possibile chiedere la dimensione di un tipo di dato o di una variabile in memoria attraverso l istruzione sizeof size_t sizeof(oggetto) size_t sizeof(tipo) typedef restituisce un valore di tipo size_t: - esso è un typedef di int, ovvero un intero E necessario includere il file stddef.h #include <stddef.h>

malloc() void * malloc ( size_t S); La funzione malloc alloca un blocco di memoria della dimensione di S byte, e restituisce : - un puntatore void con l indirizzo dello spazio allocato correttamente; - NULL se la memoria disponibile è insufficiente. Per ottenere un puntatore a tipi diversi da void, occorre effettuare un operazione di cast sul valore restituito: - lo spazio di memoria assegnato può contenere dati di qualsiasi tipo.

malloc() Se size è 0, malloc alloca un elemento di lunghezza NULLA nello heap e ne restituisce l indirizzo. Occorre sempre controllare il valore restituito da malloc, anche se la memoria richiesta è piccola. malloc alloca memoria almeno di Size byte, ma il blocco occupato può essere più grande a causa dello spazio richiesto per l allineamento dei dati e per la manutenzione dei blocchi.

calloc() void * calloc ( size_t N, size_t S); La funzione calloc alloca spazio di memoria nello heap per un array di N elementi, ciascuno di dimensioni S byte. Ogni elemento è inizializzato a zero. Per il resto calloc esegue le stesse operazioni della funzione malloc.

Deallocazione della memoria Una volta allocato un oggetto nello Heap, esso non ne viene più rimosso, anche se la procedura che lo ha allocato termina. Poiché ogni area allocata nello Heap è raggiungibile solo mediante puntatore, durante l esecuzione di un programma ogni area allocata dinamicamente deve essere accessibile attraverso un puntatore da una variabile allocata nello Stack.

Deallocazione della memoria Se ciò non avviene più poiché la variabile puntatore viene persa quell area dello Heap diventa inaccessibile dal programma pur rimanendo però allocata (ovvero inutilizzabile per le altre successive allocazioni): - Se tale caso si ripete più volte, si può avere out-of-memory E buona norma di programmazione non lasciare che ciò avvenga deallocando le aree di memoria prima che si perdano i puntatori e diventino inaccessibili.

Deallocazione della memoria Certi compilatori o linguaggi di programmazione (es. Java) sono in grado di riconoscere le aree non più raggiungibili e di rilasciarle senza che ciò sia fatto esplicitamente dal programmatore. - questa operazione si chiama Garbage Collection La garbage collection però richiede operazioni aggiuntive per individuare le aree idonee ad essere liberate e quindi una perdita di prestazioni.

free() void free ( void * BlockAddress ); La funzione free rilascia un blocco di memoria nello heap, di indirizzo BlockAddress, che sia stato precedentemente allocato con chiamate a malloc, calloc o realloc. Se BlockAddress è NULL, il puntatore è ignorato e free esegue un immediato ritorno dalla funzione. Tentativi di liberare memoria non allocata da malloc, calloc o realloc, o già liberata, possono influire sulle successive allocazioni e causare errori imprevedibili. La funzione free non restituisce alcun valore.

malloc() e free() #include <stdio.h> #include <stdlib.h> #include <malloc.h> int main() { int numero, *array, i; char buffer[15]; int allocati; numero = 100; printf("numero di elementi dell'array: %d", numero); array = (int *)malloc(sizeof(int) * numero); if (array == NULL) { } printf("memoria esauritan"); exit(1);

malloc() e free() } allocati = sizeof(int) * numero; for (i=0; i<numero; i++) { } array[i] = i; printf( \nvalori degli elementi\n"); for (i=0; i<numero; i++) { if (i%10 == 9 ) printf("%6d%c", array[i],'n ); } else printf("%6d%c", array[i], ' '); printf( \n\nnumero elementi %d\n", numero); printf("dimensione elemento %d\n", sizeof(int)); printf("bytes allocati %d\n", allocati); free(array); printf( \nmemoria Liberata\n"); return 0;

malloc() e free() In questo programma possiamo notare l'uso della funzione malloc() che ritorna un puntatore a int, corrispondente al punto di inizio, in memoria, della porzione riservata della dimensione "intera" passata come argomento Se la memoria richiesta non può essere allocata, ritorna un puntatore nullo. Nel caso citato si può notare che è stato usata la funzione sizeof per specificare il numero esatto di byte, mentre è stata usato il cast per convertire il tipo di dato "puntatore a void" a "puntatore ad int", questo per garantire che i puntatori aritmetici vengano rappresentati correttamente.

realloc() void * realloc ( void * BlockAddress, size_t NewSize ); La funzione realloc cambia la dimensione di un blocco di memoria heap precedentemente allocato con malloc, calloc o realloc il cui indirizzo iniziale è BlockAddress e lo porta a NewSize byte Restituisce un puntatore void al blocco di memoria riallocato ed eventualmente spostato: il nuovo indirizzo restituito, dunque, potrebbe essere differente da BlockAddress.

realloc() Il contenuto del blocco non è modificato per un numero di byte pari alla minore tra vecchia e nuova dimensione, anche se il nuovo blocco potrebbe risiedere in una diversa zona di memoria. Se BlockAddress è NULL e NewSize è diverso da zero, realloc è equivalente ad una malloc che alloca da zero una quantità di memoria pari a NewSize. Se non c è abbastanza memoria disponibile per espandere il blocco alla dimensione richiesta, realloc restituisce NULL e il blocco non è modificato.

realloc() Se BlockAddress è un puntatore valido e NewSize è zero, realloc libera il blocco e restituisce NULL: - In paratica si comporta come una chiamata a free(blockaddress) Per ottenere un puntatore a tipi diversi da void, occorre effettuare una operazione di cast sul valore restituito. Lo spazio di memoria assegnato può contenere dati di qualsiasi tipo.

realloc() Esempio di uso della funzione realloc() per definire un array flessibile, ovvero un array cui viene riservata della memoria suddivisa in blocchi di dimensione arbitraria. Una volta "saturato" il primo blocco, utilizziamo realloc() per allocare il blocco successivo. La suddivisione in blocchi avviene durante la fase di lettura, che essendo, appunto, dinamica, permette di minimizzare le chiamate a realloc() e di avere un dimensionamento abbastanza preciso.

realloc() #include <stdio.h> #include <stdlib.h> #include <malloc.h> int main() { char buffer[20]; int i=0, n=0, x, *array, nb; int allocati; /* byte allocati */ int dimbloc; /* byte in un blocco */ int dimint; /* byte in un intero */ int usati; /* byte contenenti interi */ nb = 1; printf("elementi in un blocco: %d\n", nb); dimint = sizeof(int); dimbloc = nb * dimint; usati = 0;

realloc() array = (int *)malloc(dimbloc); if (array == NULL) { printf("memoria insufficiente\n"); exit(1); } allocati = dimbloc; printf("allocati: %d bytes\n", allocati); printf("input di interi terminati da # :\n");

realloc() while(scanf("%d", & x)) { usati += dimint; if (usati>allocati) { allocati += dimbloc; array = (int *)realloc(array, allocati); if (array == NULL) { printf("memoria insufficienten"); exit(1); } i++; } /* in questo modo vengono letti n interi */ array[n++] = x; }

realloc() } printf( \n"); printf("allocati: %d bytes\n", allocati); printf("dim. blocchi: %d bytes\n", dimbloc); printf("dim. intero: %d bytes\n", dimint); printf("usati: %d bytes\n", usati); printf("chiamate realloc: %d\n", i); printf("numeri: %d\n", n); printf( \necco i numeri\n"); for (i=0; i<n; i++) { if (i %10 == 9) printf("%5d%c", array[i], 'n ); else printf("%5d%c", array[i], ' '); } printf("n"); return 0;