The C++ Programming Language Dynamic Memory Management
Total Page:16
File Type:pdf, Size:1020Kb
The C++ Programming Language Dynamic Memory Management Techniques Interaction with Overloading Class Sp eci c new and delete Example Outline Summary Error Handling Dynamic Memory Management Interaction with Mallo c and Free Interaction with Arrays Interaction with Constructors and Destructors Object Placement Syntax Overloading Global Op erator New Assignment to this Class Sp eci c new and delete Interaction with Inheritance 1 Dynamic Memory Management Dynamic Memory Management cont'd In C++, the new and delete op erators provide built-in language supp ort for dy- op erator new can b e either a globally de- ned function or a memb er of class T or namic memory allo cation and deallo cation. a base class of T. { Here is a minimal example of a global de nition This feature has several b ene ts: of op erator new: Reduces common programmer errors: it is easy extern "C" void *mallo c size t; to forget to multiply the numb er of objects t sz f void *op erator new size b eing allo cated by sizeof when using malloc, return mallo c sz; e.g., g // o ops, only 2 1/2 ints! int *a = int * mallo c 10; There must be only one global op era- Enhances source co de clarity: generally, there is tor new with these particular argument no need to: 1 declare op erator new and typ es in an executable. delete, 2 explicitly use casts,or 3 explicitly check the return value. { Note, it is p ossible to overhead op erator new! Improves run-time eciency: 1 users can re- { If you do not supply your own, there is one in de ne op erator new and delete globally and the C++ run-time library that's only a little also de ne them on a p er-class basis and 2 more complicated than this one. calls can b e inlined. 2 3 Error Handling Dynamic Memory Management By default, if op erator new cannot nd cont'd memory it calls a p ointer to function called new handler, e.g., op erator new, b e it lo cal or global, is only void *op erator new size t size f used for free store allo cation. void *p; while p = mallo c size == 0 { Therefore, the following do es not involve any new handler if direct invo cation of op erator new: * new handler; else Xa; return 0; Xfvoid f Xb;/*:::*/ return b; g return p; g Note, an object allo cated from the free store has a lifetime that extends beyond new handler can somehow supply mem- If its original scop e, et ory for malloc then all is ne:: : int *f int i f int *ip = new int[i]; // ::: new handler can b e set by users via Note, return ip; the set new handler function, e.g., g set new handler ::ab ort; 4 5 Interaction with Mallo c and Free Most all? C++ implementations also p ermit use of C malloc and free routines. However: Interaction with Arrays 1. Don't intermix mallo c/delete and new/free. The global new and delete op erators are 2. Be careful not to use these to allo cate C++ class objects with constructors or destructors, always used for allo cating and deallo cating e.g., arrays of class objects. class Foo f int *bar; public: When calling delete for a p ointer to an Foo void f bar = new int 100; g array, use the [] syntax to enabled de- // :: : structors to be called, e.g., ~Foo void; g; Fo o *bar = new Fo o; // OK, calls constructor class Foo f public: Foo void; ~Foo void; g Fo o *baz = mallo c sizeof *baz; Fo o *bar = new Foo[100]; // ERROR, constructor not called! Fo o *baz = new Foo; free bar; // Error, destructor not called! // ::: delete [] bar; // must have the [] delete baz; // must not have the [] Note, C++ do es not supply a realloc- style op erator. { Thus, p erforming a resize op eration may lead to increased overhead. 7 6 Interaction with Constructors and Interaction with Constructors and Destructors Destructors cont'd Here's a simple case: Allo cation and deallo cation are completely separate from construction and destruc- void fvoid f tion. Tx; g { Construction and destruction are handled by constructors and destructors. Executing f causes the following to hap- p en: { Allo cation and deallo cation are handled by op- Allo cate enough memory to hold a T; erator new and op erator delete. Construct the T in that memory; Destroy the T; Deallo cate the memory. Simil arl y, the next line has the following Note, at the time a constructor is entered, e ects: memory has already b een allo cated for the T *tp = new T; constructor to do its work. Allo cate enough memory to hold a T; If allo cation was successful, construct a T in that memory; Store the address of the memory in tp Finally, the following happ ens on deletion: Simil arl y, a destructor do es not control what happ ens to the memory o ccupied by delete tp; If tp is non-zero, the object it is destroying. destroy the T in the memory addressed by tp; free the memory addressed by tp. 8 9 Object Placement Syntax Interaction with Constructors and The C++ memory allo cation scheme pro- vides a way to construct an object in an Destructors cont'd arbitrary lo cation via an object placement syntax. Merely say: How canaprogrammer control the mem- ory allo cated for objects of typ e T? t, void *p f return p; g void *op erator new size { The answer lies in the allo cation pro cess, not Now you can do something like this: the construction pro cess. // allo cate memory in shared memory { C++ provides ne-grained control over what void *vp = shm mallo c sizeof T; it means to \allo cate enough memory to hold T *tp = new vp T; // construct a T there. a T." Because it is p ossible to construct an ob- ject in memory that has already b een al- e.g., lo cated, there must be a way to destroy an object without deallo cating its mem- ory. To do that, call the destructor di- T *tp = new T; rectly: rst set tp = op erator new sizeof T then call constructorforclass T at lo cation tp tp->T::~T ; // Note, also works on built-in typ es! shm free tp; 10 11 Overloading Global Op erator New Object Placement Syntax Memory allo cation can often b e tuned for cont'd a particular problem. { e.g., assume you never want to delete any al- The placement syntax can b e used to sup- lo cated memory: ply additional arguments to op erator new, e.g., struct align fchar x; double d;g; const int ALIGN = char *&struct align * 0->d char * 0; new T; // calls op erator new sizeof T t size f void *op erator new size new 2, f T; // calls op erator new sizeof T, 2, f static char *buf start = 0; end = 0; static char *buf e.g., provide a C++ interface to vector- static int buf size = 4 * BUFSIZ; resize via reallo c::: char *temp; size = size + ALIGN 1 / ALIGN * ALIGN; start + size >= buf end f if buf /* Note, this only works sensibly for built-in typ es, buf size *= 2; due to constructor/destructor issues::: */ size = MAX buf size, size; buf static inline void * if buf start = mallo c buf size t size, void *ptr, size t new len f op erator new size buf end = buf start + buf size; return ptr == 0? mallo c size * new len else len * size; : reallo c ptr, new return 0; g g // ::: temp = buf start; char *p = new 0, 100 char; buf start += size; p = new p, 1000 char; return temp; g 12 13 Assignment to this cont'd Assignment to this In C++ releases prior to 2.0, if a user Typical memory management approach: wanted to eliminate typ edef char ELEMENT; 1 f class Stack the problems describ e ab ove, the only way was to a private: typ edef char ELEMENT; int top , max ; 2 f class Stack ELEMENT *stack ; private: public: , max ; int top enum fDEFAULT SIZE = 100g; ELEMENT stack [1]; Stack 1int size = Stack 1::DEFAULT SIZE f ~Stack 2void f delete void * this; this = 0; g this->stack = new ELEMENT[size]; // the cast is essential! this->max = size; public: this->top = 0; SIZE = 100g; enum fDEFAULT g 2int size = Stack 2::DEFAULT SIZE f Stack // :::push, p op, top, is empty,is full, etc. int nbytes = sizeof *this + ~Stack 1void f delete this->stack ; g ; size 1 * sizeof *this->stack g; this = Stack 2* new char[nbytes]; Stack 1 *s1 = new Stack 1; // defaults to 100 this->max = size; this->top = 0; However, this has three problems: g // :::push, p op, top, is empty,is full, etc. void disp ose void f 1 Extra allo cation p er dynamic object creation. this->Stack 2::~Stack 2 ; 2 Extra indirection on every access to this->stack; g 3 Extra \allo cation wrapp er" overhead in the constructor. g; 15 14 Assignment to this cont'd Assignment to this cont'd However, assigning to this is now consid- ered a language anachronism for several reasons: s2 s1 top top 1. It is easy to make a mistake:: : max max 2. It is not transparent, e.g., stack { Using assignment to this also means that all stack objects must b e allo cated on the free store.