Memory Management. Local Storage. Global Storage. Delete esplicite



Похожие документы
Allocazione dinamica della memoria - riepilogo

Inizializzazione, Assegnamento e Distruzione di Classi

Visibilità dei Membri di una Classe

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

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

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

Funzioni in C. Violetta Lonati

costruttori e distruttori

Oggetti Lezione 3. aspetti generali e definizione di classi I


VARIABILI LOCALI E GLOBALI (ESTERNE)

I puntatori e l allocazione dinamica di memoria

Generalizzazione di funzioni e di classi. Macro come funzioni generiche

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

Concetto di Funzione e Procedura METODI in Java

dall argomento argomento della malloc()

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:

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

La prima applicazione Java. Creazione di oggetti - 1. La prima applicazione Java: schema di esecuzione. Gianpaolo Cugola - Sistemi Informativi in Rete

Const, friend, static,this

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

puntatori Lab. Calc. AA 2007/08 1

Laboratorio di programmazione

void funzioneprova() { int x=2; cout<<"dentro la funzione x="<<x<<endl; }

GESTIONE INFORMATICA DEI DATI AZIENDALI

Funzioni. Il modello console. Interfaccia in modalità console

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

Grammatica di base: Pointers

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

La struttura dati ad albero binario

12 - Introduzione alla Programmazione Orientata agli Oggetti (Object Oriented Programming OOP)

Le stringhe. Le stringhe

Eredità in C++ Corso di Linguaggi di Programmazione ad Oggetti 1. a cura di Giancarlo Cherchi

Programmazione a Oggetti Lezione 10. Ereditarieta

strutturare dati e codice

Codifica: dal diagramma a blocchi al linguaggio C++

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

13 - Gestione della Memoria nella Programmazione Orientata agli Oggetti

Introduzione al linguaggio C Gli array

Variabili e tipi di dato

Java:Struttura di Programma. Fabio Scanu a.s. 2014/2015

Realizzazione di una classe con un associazione

Uso di JUnit. Fondamenti di informatica Oggetti e Java. JUnit. Luca Cabibbo. ottobre 2012

La gestione della memoria

Corso di Fondamenti di Informatica

Informatica 3. LEZIONE 7: Fondamenti di programmazione orientata agli oggetti (1)

Realizzazione di Politiche di Gestione delle Risorse: i Semafori Privati

Introduzione alla programmazione in C

GESTIONE DEI PROCESSI

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

Programmazione Orientata agli Oggetti in Linguaggio Java

Introduzione al Linguaggio C

Modulo 4: Ereditarietà, interfacce e clonazione

Linguaggio C - Funzioni

Linguaggio C - Stringhe

Corso di Informatica

Soluzione dell esercizio del 2 Febbraio 2004

Programmazione in Java Parte I: Fondamenti

Appello di Informatica B

Matematica - SMID : Programmazione Febbraio 2009 FOGLIO RISPOSTE

Guida all utilizzo del compilatore lcc-win32 per creare una applicazione console

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

Tipi di Dato Ricorsivi

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

10.1. Un indirizzo IP viene rappresentato in Java come un'istanza della classe InetAddress.

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

Record in C: il costruttore struct.

Utilizzo e scrittura di classi

Introduzione. Java. Composizione. Esempio -- composizione. G. Prencipe È qualcosa che abbiamo già visto varie volte

INFORMATICA - I puntatori Roberta Gerboni

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica

Le variabili. Olga Scotti

Java: Compilatore e Interprete

Bloodshed Dev-C++ è l IDE usato durante le esercitazioni/laboratorio. IDE = Integrated Development Environment

Progettazione : Design Pattern Creazionali

Corso di Programmazione ad Oggetti

3. La sintassi di Java

Registratori di Cassa

INFORMATICA 1 L. Mezzalira

Parola chiave extends

Puntatori Passaggio di parametri per indirizzo

LINGUAGGI DI PROGRAMMAZIONE

Programmazione Java: Variabili membro, Metodi La parola chiave final

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

Struttura di un programma Java

Assembler di Spim. Assembler di SPIM. Struttura di un programma assembler. Direttive

Per scrivere una procedura che non deve restituire nessun valore e deve solo contenere le informazioni per le modalità delle porte e controlli

Stored Procedures. Massimo Mecella Dipartimento di Ingegneria informatica automatica e gestionale Antonio Ruberti Sapienza Università di Roma

Tale attività non è descritta in questa dispensa

Gestione dei File in C

Reflection in Java. Linguaggi Corso M-Z - Laurea in Ingegneria Informatica A.A

MANUALE PARCELLA FACILE PLUS INDICE

Dispensa YACC: generalità

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

Транскрипт:

Memory Management Costruzione di Interfacce Lezione 13 Dal Java al C++ cignoni@iei.pi.cnr.it http://vcg.iei.pi.cnr.it/~cignoni Due grandi categorie di storage: Local, memoria valida solo all interno di un certo scope (e.g. dentro il corpo di una funzione), lo stack; Global, memoria valida per tutta l esecuzione del programma, lo heap. 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 2 Local Storage int myinteger; // memory for an integer allocated //... myinteger is used here... Bar bar; // memory for instance of class Bar allocated //... bar is used here... Global Storage Per allocare memoria nel global storage (e.g. per avere puntatori ad oggetti la cui validità persista sempre) si usa l operatore new. e sono i delimitatori di un blocco in c++, Non è detto che corrisponda ad una funzione Non possiamo usare bar, o myinteger fuori dallo scope del blocco! 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 3 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 4 Delete esplicite [Bar.H] class Bar Bar(); Bar(int a); void myfunction(); // this method would be defined // elsewhere (e.g. in Bar.C) protected: int m_a; ; Bar::Bar() m_a = 0; Bar::Bar(int a) m_a = a; [main.c] #include "Bar.H" int main(int argc, char *argv[]) // declare a pointer to Bar; no memory for a Bar instance is // allocated now p currently points to garbage Bar * p; // create a new instance of the class Bar (*p) // store pointer to this instance in p p = new Bar(); if (p == 0) // memory allocation failed return 1; // since Bar is in global storage, we can still call methods on it // this method call will be successful p->myfunction(); 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 5 In java si alloca con new e la memoria viene liberata automaticamente dal garbage collector In c++ NO. Ci deve pensare l utente a disallocare esplicitamente quel che ha esplicitanmente allocato con una new delete p; // memory pointed to by p is deallocated Solo oggetti creati con new possono essere deallocati con delete. 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 6 1

Memory Management Memory Management [Foo.H] #include "Bar.H" class Foo private: Bar* m_barptr; Foo() ~Foo() void funca() m_barptr = new Bar; void funcb() // use object *m_barptr void funcc() //... delete m_barptr; ; Foo myfoo; // create local instance of Foo myfoo.funca(); // memory for *m_barptr is allocated //... myfoo.funcb(); //... myfoo.funcb(); //... myfoo.funcc(); // memory for *m_barptr is deallocated 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 7 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 8 Memory Management Costruttori e Distruttori Foo myfoo; //... myfoo.funcb(); // oops, bus error in funcb() myfoo.funca(); // memory for *m_barptr is allocated myfoo.funca(); // memory leak, you lose track of the memory previously // pointed to by m_barptr when new instance stored //... myfoo.funcb(); La soluzione corretta è quella di delegare il compito di allocare e disallocare ai costruttori e distruttori degli oggetti // memory leak! memory pointed to by m_barptr in myfoo // is never deallocated 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 9 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 10 Istanze, puntatori e riferimenti [Foo.H] #include "Bar.H" class Foo private: Bar* m_barptr; Foo(); ~Foo(); void funca()... void funcb() // use object *m_barptr void funcc()... ; Piccolo riepilogo L allocazione, disallocazione della memoria delle istanze degli oggetti è gestita automaticamente. Quando una variabile esce dal proprio scope la sua mem è disallocata (anche se c era un puntatore che la riferiva) I puntatori ottenuti tramite new sono relativi a porzioni di memoria di l utente ha la responsabilità I riferimenti sono semplicemente nomi differenti con cui si riferisce altre variabili/oggetti, quindi non si può/deve gestirne direttamente la memoria (ma si deve gestire la mem della variabile cui si riferiscono). Foo::Foo() m_barptr = new Bar; Foo::~Foo() delete m_barptr; 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 11 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 12 2

Parametri In java il passaggio di parametri è sempre per riferimento, cioè si può cambiare un oggetto usandolo come argomento di una funzione In c++ i parametri possono essere passati per riferimento o per valore (default) void IncrementByTwo(int foo) foo += 2; // foo non cambia void IncrementByTwo(int &foo) foo += 2; // foo cambia Alternativamente, si può ottenere lo stesso effetto passando (per valore) un puntatore Valori di ritorno I valori di ritorno di funzione possono essere, al solito, istanze puntatori o riferimenti Errore frequente, restituire riferimenti o puntatori a istanze locali alla funzione Tali istanze sono distrutte al ritorno dalla funzione, quindi si ha puntatori o riferimenti a cose non più allocate void IncrementByTwo(int* fooptr) *fooptr += 2; 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 13 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 14 Errore return 1 Errore ritorno 2 [FooFactory.C] #include "FooFactory.H" #include "Foo.H" Foo* FooFactory::createBadFoo(int a, int b) Foo LocInst (a,b); // creates an local instance of class Foo return & LocInst; // returns a pointer to this instance Foo& FooFactory::createBadFoo(int a, int b) Foo alocalfooinstance(a,b); // creates an local instance // of the class Foo return alocalfooinstance; // returns a reference to this // instance // EEK! alocalfooinstance leaves scope and is destroyed! // ERROR! LocInst leaves scope // and it is destroyed! 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 15 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 16 Soluzione corretta Foo* FooFactory::createFoo(int a, int b) return new Foo(a,b); // returns a pointer to an instance of Foo Foo FooFactory::createFoo(int a, int b) return Foo(a,b); // returns an instance of Foo morale: MAI ritornare puntatori a oggetti che non sono stati generati con new, a meno che non si sia estremamente sicuri che le variabili cui si riferiscano non escano dallo scope Per chi viene dal C Differenze tra new e malloc Malloc non conosce per che cosa serve la memoria e quindi è l utente a dover fare I conti di quanta ne serve Malloc non inizializza (calloc inizializza solo a valori costanti),new chiama il costruttore per ogni oggetto allocato Similarmente delete chiama il distruttore per ogni oggetto disallocato MAI mescolare new e malloc 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 17 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 18 3

New e delete di array Obj *op = new Obj[20]; // allocates 20 Obj Per ogni oggetto allocato viene chiamato il costruttore Notare che la delete deve essere fatta con la delete per array delete [] op; Esempio class Person Person() Person(char const *n, char const *a, char const *p); ~Person(); char const *getname() const; char const *getaddress() const; char const *getphone() const; ; private: // data fields char *name; char *address; char *phone; 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 19 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 20 Class Person Scopo del costruttore è inizializzare i campi dell oggetto #include "person.h" #include <string.h> Person::Person(char const *n, char const *a, char const *p) name = strdupnew(n); address = strdupnew(a); phone = strdupnew(p); Strdup con new Dove char *strdupnew(char const *str) return str? strcpy(new char [strlen(str) + 1], str) : 0; questo per essere sicuri di non mescolare malloc e new (strdup usa malloc!) 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 21 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 22 Tipico uso #include "person.h" #include <string.h> Person::~Person() delete name; delete address; delete phone; #include "person.h" #include <iostream> void showperson() Person karel("karel", sdfdfdee", "038 420 1971"), *frank = new Person("Frank", "Oostu", "050 403 2223"); cout << karel.getname() << ", " << karel.getaddress() << ", " << karel.getphone() << endl << frank->getname() << ", " << frank->getaddress() << ", " << frank->getphone() << endl; delete frank; 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 23 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 24 4

Esempio2 Person::~Person()cout <<"Person destructor called"<< endl; int main() Person *a = new Person[2]; cout << "Destruction with []'s" << endl; delete [] a; a = new Person[2]; cout << "Destruction without []'s" << endl; delete a; return 0; Generated output: Destruction with []'s Person destructor called Person destructor called Destruction without []'s Person destructor called */ 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 25 Il precedente esempio generava memory leaks, solo il distruttore del primo elemento viene chiamato se si usa la sintassi sbagliata della delete 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 26 Esempio3 Person::~Person()cout <<"Person destructor called"<< endl; int main() Person **a; a = new Person* [2]; a[0] = new Person [2]; a[1] = new Person [2]; Nessun output perché a è un array di puntatori. La disallocazione di un puntatore (e quindi di NON di un oggetto) non comporta alcuna azione. Ogni elemento dell array andrebbe disallocato singolarmente. delete [] a; return 0; No Output!! 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 27 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 28 Operatore assegnamento L operatore di assegnamento di default in C++ fa la copia byte a byte dei campi delle due strutture. Se si usa puntatori questo è assai pericoloso Operatore Assegnamento void printperson(person const &p) Person tmp; tmp = p; cout << "Name: "<< tmp.getname() << endl << "Address: "<< tmp.getaddress()<< endl << "Phone: "<< tmp.getphone() << endl; 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 29 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 30 5

Operatore Assegnamento Operatore Assegnamento Il problema è dovuto al fatto che l operatore assegnamento ha fatto la copy bytewise dei puntatori ignorando il loro significato Alla fine p contiene puntatori a memoria disallocata! Approccio giusto: 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 31 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 32 Overloading Operatore = In c++ si può fare overload dei vari operatori Sintassi Basta definire una funzione chiamata operator=( ) Si può fare per I vari operatori operator+() Ecc. Operator = Person &Person::operator=(Person const &other) if (this!= &other) delete address; delete name; delete phone; address = strdupnew(other.address); name = strdupnew(other.name); phone = strdupnew(other.phone); // return current object. The compiler will // make sure that a reference is returned return *this; 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 33 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 34 Note operator= a=b è equivalente a a.operator=(b); if(this!=other) serve per evitare l autoassegnamento (altrimenti facendo p=p si distruggerebbe le stringhe prima di poterle copiare) Il valore di ritorno serve per l assegnamento multiplo a=b=c; (in C++ anche l assegnamento è un expr.) Costruttore di copia Costruttori che hanno in ingresso un riferimento ad un oggetto della stessa classe Serve per inizializzare una variabile con un altra class Person Person(Person const &other); ; 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 35 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 36 6

Costruttori di copia e assegnamento Entrambi devono duplicare un oggetto Il costruttore di copia non deve disallocare memoria (l oggetto è stato appena creato) Il costruttore di copia non deve fare controlli di autoassegnamento (non si può inizializzare una var con se stessa) Costruttori di copia e parametri void nameof(person p) // no pointer, no reference // but the Person itself cout << p.getname() << endl; il costruttore di copia è chiamato quando si passa un oggetto per valore 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 37 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 38 Costruttore di copia e return value Person getperson() string name, address, phone; cin >> name >> address >> phone; Person p(name.c_str(), address.c_str(),phone.c_str()); Const e parametri Quando modifica una dichiarazione di dati, const specifica che l oggetto o la variabile non è modificabile Quando segue la lista dei parametri di una funzione membro, const specifica che la funzione non modifica l oggetto per cui è invocata. const int i = 5; i = 10; // Error i++; // Error return p; // returns a copy of `p'. il costruttore di copia è chiamato quando una funzione restituisce un istanza di un oggetto. 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 39 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 40 Const e puntatori char *const aptr = mybuf; // Constant pointer // non posso cambiare il valore (indirizzo) // del puntatore *aptr = 'a'; // Legal aptr = yourbuf; // Error un puntatore ad una variabile const può essere assegnato solo ad un puntatore che è dichiarato const const char *bptr = mybuf;// Pointer to constant data // non posso cambiare il contenuto della locazione // puntata. *bptr = 'a'; // Error bptr = yourbuf; // Legal può essere usato per impedire ad una funzione di cambiare un parametro passato per puntatore Trucco leggere da destra a sinistra Const e riferimenti Un uso importante dei riferimenti costanti è il loro uso nel passaggio di parametri void printperson (Person const &p) Si evita di invocare il costruttore di copia, pur rimanendo sicuri che non modifica l oggetto 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 41 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 42 7

Morale Se la nostra classe contiene puntatori conviene sempre scrivere accuratamente Costruttore Costruttore di copia Operatore di assegnamento Distruttore Template I Template sono un meccanismo che permette di definire funzioni e classi basate su argomenti e oggetti dal tipo non specificato template class <T> swap(t &a, T &b); template class <T> class List...; Queste funzioni e oggetti generici diventano codice completo una volta che le loro definizioni sono usate con oggetti reali 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 43 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 44 Esempio di template di funzione Scambio tra due oggetti generici: template <class T> void swap(t &a, T &b) T tmp = a; a = b; b = tmp; int main() int a = 3, b = 16; double d = 3.14, e = 2.17; swap(a, b); swap(d, e); // swap (d, a); errore in compilazione! return (0); Template Osservazioni Notare che la definizione di una funzione template è simile ad una macro, nel senso che la funzione template non è ancora codice, ma lo diventerà una volta che essa viene usata Il fatto che il compilatore generi codice concreto solo una volta che una funzione è usata ha come conseguenza che una template function non può essere mai raccolta in una libreria a run time Un template dovrebbe essere considerato come una sorta di dichiarazione e fornito in un file da includere. 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 45 30 Ott 2002 Costruzione di Interfacce - Paolo Cignoni 46 8