Download presentation
Presentation is loading. Please wait.
1
C++: MEMORY MANAGEMENT, SUMMARY ID1218 Lecture 102009-11-30 Christian Schulte cschulte@kth.se Software and Computer Systems School of Information and Communication Technology KTH – Royal Institute of Technology Stockholm, Sweden
2
Overview Memory management case studies resizable arrays freelists reference counting Summary C and C++ summary… … and questions you should be able to answer L10, 2009-11-30ID1218, Christian Schulte 2
3
Case studies Memory Management L10, 2009-11-30 3 ID1218, Christian Schulte
4
Memory Management How to… fit C++ structure, example: resizable arrays make efficient, example: free lists Who does what? who allocates? who is responsible for deallocation? example: reference counting L10, 2009-11-30ID1218, Christian Schulte 4
5
Resizable Arrays L10, 2009-11-30 5 ID1218, Christian Schulte
6
Resizable Arrays Should behave like an array the number of elements can be changed provides correct construction, deletion, assignment supports array access operator [] can be passed as constant reference polymorphic with respect to element type can be mixed with "normal" arrays L10, 2009-11-30ID1218, Christian Schulte 6
7
Resizable Arrays Members current size: unsigned int element array: *Element First attempt for integers make polymorphic in last step L10, 2009-11-30ID1218, Christian Schulte 7
8
Resizable Arrays: Class class IRA { private: unsigned int _n; int* _x; public: IRA(unsigned int n=8); IRA(const IRA& ira); IRA& operator=(const IRA& ira); void resize(unsigned int n); int get(unsigned int i) const; void set(unsigned int i, int x); ~IRA(); }; L10, 2009-11-30ID1218, Christian Schulte 8
9
Constructor class IRA { private: … public: IRA(unsigned int n=8) : _n(n), _x(new int[_n]) {} … }; Any member function defined inside class is inline Member functions can also be defined outside L10, 2009-11-30ID1218, Christian Schulte 9
10
Inline Definition class IRA { private: … public: IRA(unsigned int n=8); … }; inline IRA::IRA(unsigned int n) : _n(n), _x(new int[_n]) {} Any member function defined inside class is inline Member functions can also be defined outside L10, 2009-11-30ID1218, Christian Schulte 10
11
Outline Definition Header file: class IRA { private: … public: IRA(unsigned int n=8); … }; Implementation file IRA::IRA(unsigned int n) : _n(n), _x(new int[_n]) {} L10, 2009-11-30ID1218, Christian Schulte 11
12
Copy Constructor IRA::IRA(const IRA& ira) : _n(ira._n), _x(new int[_n]) { for (unsigned int i=0; i<_n; i++) _x[i] = ira._x[i]; } Design: nothing shared between copies L10, 2009-11-30ID1218, Christian Schulte 12
13
Destructor IRA::~IRA() { delete [] _x; } Design: nothing shared between copies L10, 2009-11-30ID1218, Christian Schulte 13
14
Assignment Operator IRA& IRA::operator=(const IRA& ira) { if (this != &ira) { delete [] _x; _n = ira._n; _x = new int[_n]; for (unsigned int i=0; i<_n; i++) _x[i] = ira._x[i]; } return *this; } Design: nothing shared between copies L10, 2009-11-30ID1218, Christian Schulte 14
15
Access inline int IRA::get(unsigned int i) const { return _x[i]; } inline void IRA::set(unsigned int i, int x) { _x[i]=x; } Must go into header file L10, 2009-11-30ID1218, Christian Schulte 15
16
Access: Assert Proper Use inline int IRA::get(unsigned int i) const { assert(i < _n); return _x[i]; } inline void IRA::set(unsigned int i, int x) { … } Checked at runtime requires #include runtime error, if violated (can be looked for in debugger) ignored, if the macro NDEBUG is defined pass –DNDEBUG from commandline L10, 2009-11-30ID1218, Christian Schulte 16
17
Resizing the Array void IRA::resize(unsigned int n) { int* x = new int[n]; unsigned int m = std::min(n,_n); for (unsigned int i=0; i<m; i++) x[i] = _x[i]; delete [] _x; _n = n; _x = x; } std::min requires #include L10, 2009-11-30ID1218, Christian Schulte 17
18
Overloading [] : First Attempt class IRA { private: unsigned int _n; int* _x; public: IRA(unsigned int n=8); IRA(const IRA& ira); IRA& operator=(const IRA& ira); void resize(unsigned int n); int operator[](unsigned int i); ~IRA(); }; L10, 2009-11-30ID1218, Christian Schulte 18
19
Overloading [] : First Attempt inline int IRA::operator[](unsigned int i) { assert(i < n); return _x[i]; } Does not work: ira[7] = 4; must pass a reference instead Does not work: ira[7] if ira is const IRA& must also provide const version L10, 2009-11-30ID1218, Christian Schulte 19
20
Overloading [] : Second Attempt class IRA { private: unsigned int _n; int* _x; public: IRA(unsigned int n=8); IRA(const IRA& ira); IRA& operator=(const IRA& ira); void resize(unsigned int n); int& operator[](unsigned int i); const int& operator[](unsigned int i) const; ~IRA(); }; L10, 2009-11-30ID1218, Christian Schulte 20
21
Overloading [] : Second Attempt inline int& IRA::operator[](unsigned int i) { assert(i < n); return _x[i]; } Works for: ira[7] = 4; passes a reference to position in array L10, 2009-11-30ID1218, Christian Schulte 21
22
Overloading [] : Second Attempt inline const int& IRA::operator[](unsigned int i) const { assert(i < n); return _x[i]; } Works for ira[7] if ira is const IRA& provides const version L10, 2009-11-30ID1218, Christian Schulte 22
23
Generic Resizable Arrays template class RA { private: unsigned int _n; T* _x; public: RA(unsigned int n=8); RA(const RA & ra); RA & operator=(const RA & ra); void resize(unsigned int n); T& operator[](unsigned int i); const T& operator[](unsigned int i) const; ~RA(); }; L10, 2009-11-30ID1218, Christian Schulte 23
24
Generic Copy Constructor template RA ::RA(const RA & ra) : _n(ra._n), _x(new T[_n]) { for (unsigned int i=0; i<_n; i++) _x[i] = ra._x[i]; } Define in header file What is executed: default constructor? yes! copy constructor? no! assignment operator? yes! L10, 2009-11-30ID1218, Christian Schulte 24
25
Mixing With Normal Arrays RA x(42); void f(int* a); void g(int a[]); f(x); g(x); Both calls do not work: x is of type RA Simple solution: f(&x[0]); g(&x[0]); L10, 2009-11-30ID1218, Christian Schulte 25
26
Mixing With Normal Arrays template class RA { … public: … operator T*(void) { return _x; } }; Dangerous… RA x(42); int* y = x; x.resize(1024); y[0] = 4; L10, 2009-11-30ID1218, Christian Schulte 26
27
Freelists L10, 2009-11-30 27 ID1218, Christian Schulte
28
Efficient Lists Common behavior create and delete list cells very often Memory allocation and deallocation is expensive Idea store allocated but unused list cells in a freelist allocate from freelist whenever possible deallocate to freelist L10, 2009-11-30ID1218, Christian Schulte 28
29
Integer Lists class IL { private: int _hd; IL* _tl; public: IL(int h, IL* t = NULL); int hd() const; void hd(int h); IL* tl() const; void tl(IL* t); }; Basic required functionality no default constructor, no … Naïve memory policy: delete single list cell refine, if different policy needed L10, 2009-11-30ID1218, Christian Schulte 29
30
Integer Lists inline IL::IL(int h, IL* t) : _hd(h), _tl(t) {} inline int IL::hd() const { return _hd; } inline void IL::hd(int h) { _hd=h; } inline IL* IL::tl() const { return _tl; } inline void IL::tl(IL* t) { _tl=t; } L10, 2009-11-30ID1218, Christian Schulte 30
31
Overloading Memory Allocation #include class IL { private: int _hd; IL* _tl; public: IL(int h, IL* t = NULL); int hd() const; void hd(int h); IL* tl() const; void tl(IL* t); static void* operator new(size_t s); static void operator delete(void* p); }; L10, 2009-11-30ID1218, Christian Schulte 31
32
Overloading Memory Allocation inline void* IL::operator new(size_t s) { return malloc(s); } inline void IL::operator delete(void* p) { free(p); } Same behavior as before L10, 2009-11-30ID1218, Christian Schulte 32
33
Freelist as Static Member #include class IL { private: int _hd; IL* _tl; static IL* _free; public: IL(int h, IL* t = NULL); int hd() const; void hd(int h); IL* tl() const; void tl(IL* t); static void* operator new(size_t s); static void operator delete(void* p); static void flush(); }; L10, 2009-11-30ID1218, Christian Schulte 33
34
Implementation File: Broken IL* IL::_free = NULL; void IL::flush() { for (IL* f=_free; f!=NULL; f=f->_tl) free(f); _free = NULL; } Freelist is initially empty Access after free! L10, 2009-11-30ID1218, Christian Schulte 34
35
Implementation File: Better IL* IL::_free = NULL; void IL::flush() { IL* f=_free; while (f!=NULL) { IL* t = f->_tl; free(f); f = t; } _free = NULL; } L10, 2009-11-30ID1218, Christian Schulte 35
36
Allocating from the Freelist inline void* IL::operator new(size_t s) { if (_free == NULL) { return malloc(s); } else { IL* il = _free; _free = _free->_tl; return il; } Same behavior as before L10, 2009-11-30ID1218, Christian Schulte 36
37
Deallocating to the Freelist inline void IL::operator delete(void* p) { IL* il = static_cast (p); il->_tl = _free; _free = il; } L10, 2009-11-30ID1218, Christian Schulte 37
38
Generic Freelists Not straightforward no static members in parametric classes Solution implement type independent freelist manager pass freelist manager as extra argument to new and delete (placement new and delete) read a book… L10, 2009-11-30ID1218, Christian Schulte 38
39
Reference Counting L10, 2009-11-30 39 ID1218, Christian Schulte
40
Sharing Arrays Desired functionality resizable array without copies (use a lot of memory) same array What memory management policy unshared arrays: whoever created array is responsible (directly or indirectly) to delete shared array: when is the array not any longer used? L10, 2009-11-30ID1218, Christian Schulte 40
41
Reference Counting Separate array proper:store elements handle:implement allocation protocol provide access to array proper Store in array proper: reference count …how many handles refer to array array creation through handle: just one when array becomes shared through additional handle: increment when handle is deleted: decrement if reference count hits zero: delete array L10, 2009-11-30ID1218, Christian Schulte 41
42
Array Object Proper class AO { public: unsigned int n; int* x; unsigned int rc; }; L10, 2009-11-30ID1218, Christian Schulte 42
43
Array Handle class AH { private: AO* _ao; public: AH(unsigned int n=8); AH(const AH& ah); AH& operator=(const AH& ah); ~AH(); int& operator[](unsigned int i); … }; L10, 2009-11-30ID1218, Christian Schulte 43
44
Array Handle Constructor AH::AH(unsigned int n) : _ao(new AO) { _ao->n = n; _ao->x = new int[n]; _ao->rc = 1; } L10, 2009-11-30ID1218, Christian Schulte 44
45
Array Handle: Object Access inline int& AH::operator[](unsigned int i) { return _ao->x[i]; } … L10, 2009-11-30ID1218, Christian Schulte 45
46
Array Handle Destructor inline AH::~AH() { _ao->rc--; if (_ao->rc == 0) { delete [] _ao->x; delete _ao; } Only if no more handles refer to object, delete object Different design: provide constructor and destructor for array object L10, 2009-11-30ID1218, Christian Schulte 46
47
Copy Constructor inline AH::AH(const AH& ah) : _ao(ah._ao) { _ao->rc++; } Array object is used by one additional handle L10, 2009-11-30ID1218, Christian Schulte 47
48
Assignment Operator inline AH::operator=(const AH& ah) { if (this != &ah) { if (--_ao->rc == 0) { delete _ao->x; delete _ao; } _ao = ah._ao; _ao.rc++; } return *this; } Unsubscribe handle from current object possibly delete object Subscribe to new object L10, 2009-11-30ID1218, Christian Schulte 48
49
Putting the Object at its Place… class AH { private: class AO { public: unsigned int n; int* x; unsigned int rc; }; AO* _ao; public: AH(unsigned int n=8); … }; Object should never be used without controlling handle L10, 2009-11-30ID1218, Christian Schulte 49
50
Smart Pointers Generic wrapper class overloading operators -> and * Part of C++ standard library Use reference counting inside L10, 2009-11-30ID1218, Christian Schulte 50
51
Problems With Reference Counting Cost every assignment and copy is expensive all access has to go through one additional indirection Cyclic datastructures suppose reference counted lists create cyclic list all reference counts in cycle will be at least one never deleted L10, 2009-11-30ID1218, Christian Schulte 51
52
Summary: Basics L10, 2009-11-30ID1218, Christian Schulte 52
53
L10, 2009-11-30ID1218, Christian Schulte Integer Types Basic integer type int no guarantee on range in C++ today, often 32 bits, anytime soon 64 bits, … depends on machine (think of embedded…) Can be augmented with short or long int never shorter than s hort int (at least 16 bits) int never longer than long int (at least 32 bits ) Can be modified with signed (default) or unsigned short signed int -32768 … 32767 short unsigned int 0 … 65535 just for example! 53
54
L10, 2009-11-30ID1218, Christian Schulte Floating Point Types Single precision float often: 32 bits Double precision double often: 64 bits 54
55
L10, 2009-11-30ID1218, Christian Schulte Character Type Character type char no guarantee on size, often 8 bits (ASCII, not Unicode!) unspecified whether signed or unsigned Character constants in single quotes 'a', '1' escape sequences: '\n' for newline, etc Also available: wchar_t for wide characters 55
56
L10, 2009-11-30ID1218, Christian Schulte Boolean Type Boolean type bool constants true and false Rather late addition! watch out for int with zero as false and any other value true! 56
57
L10, 2009-11-30ID1218, Christian Schulte Constants Variables taking an immutable value cannot be changed abbreviation for commonly used values Use const modifier const double pi = 3.1415; assignment to pi not possible 57
58
L10, 2009-11-30ID1218, Christian Schulte Operators and Expressions No left to right order readInt() – readInt() with input 2 and 3 can be either 1 or -1 Integer division not guaranteed to round towards zero (book uses down) 8/-5 can be either -1 or -2 Comma operator: a,b evaluates to b weird things possible! 58
59
L10, 2009-11-30ID1218, Christian Schulte Unitialized Variables Variables not by guarantee initialized unless global or static Always give initial value important for objects 59
60
L10, 2009-11-30ID1218, Christian Schulte Static Casts Cast at least one into double static_cast (x)/y; Other casts dynamic_cast casting objects, later const_cast later reinterpret_cast just do it as long size fits… C-style cast ((double) x) dangerous, combines everything, don't use! 60
61
L10, 2009-11-30ID1218, Christian Schulte Example Questions What is the relation between sizeof(int) sizeof(short int) sizeof(long int) Answer sizeof(short int) sizeof(int) sizeof(int) sizeof(long int) 61
62
Summary: Arrays and Pointers L10, 2009-11-30ID1218, Christian Schulte 62
63
L10, 2009-11-30ID1218, Christian Schulte C-style Arrays C-style arrays int a[42]; creates an array of 42 integers access cout << a[1]; assignment a[1] = a[2]+a[3]; ranges from a[0] to a[41] Dimension of array must be constant can be evaluated at compile time to constant (eg 2*4 ) illegal int a[n] where n is variable! 63
64
L10, 2009-11-30ID1218, Christian Schulte Arrays are Pointers C-Style arrays are basically pointers point to beginning of array Array access a[i] translates to *(a+i) Common idiom: pointer arithmetic pointer +/- integer: offset to pointer pointer – pointer: distance between pointers 64
65
L10, 2009-11-30ID1218, Christian Schulte Creating Dynamic Arrays An array of size n int* a = new int[n]; Release memory later delete [] a; never forget the [] : important for arrays of objects (calling destructor) 65
66
L10, 2009-11-30ID1218, Christian Schulte Example Questions Is this legal? int n = 6; int a[n]; const int n = 5; int b[n*4]; Answer no yes 66
67
L10, 2009-11-30ID1218, Christian Schulte Example Questions Value of x and y … int a[] = {4,6,8}; int b[] = {1,3,5}; int x = *(a+5-*(b+1)); *(b+a[1]-a[0]) = *a; int y = *a+*(b+(&b[2]-&b[0])); value of x : *(a+5-*(b+1)) = a[5-b[1]] = a[5-3] = a[2] = 8 assignment: b[a[1]-a[0]] = a[0], that is b[2]=a[0] value of y : a[0] + b[b+2-b] = a[0] + b[2] = 4 + 4 = 8 67
68
Summary: Functions L10, 2009-11-30ID1218, Christian Schulte 68
69
L10, 2009-11-30ID1218, Christian Schulte Functions: Issues Overloading Declarations Definitions Default parameters Inline functions Call-by-value and call-by-reference 69
70
L10, 2009-11-30ID1218, Christian Schulte Example Questions Is this legal? int f(int); double f(double x) { return x+1.0; } yes, absolutely! 70
71
L10, 2009-11-30ID1218, Christian Schulte Example Questions What is the value of z? int f(double x) { return static_cast (x)-1; } int f(int* x) { return *(x+1); } int f(int x, int y=4) { return x+y-1; } int a[] = {1,2,3}; int z = a[f(1.0)]-f(1)+f(7,5)+f(&a[1]); f(1.0) = 0 f(1) = 1+4-1 = 4 f(7,5) = 7+5-1 = 11 f(&a[1]) = *(a+2) = 3 71
72
Summary: Objects and Classes L10, 2009-11-30ID1218, Christian Schulte 72
73
L10, 2009-11-30ID1218, Christian Schulte Accessors vs Mutators Fundamental difference change object state:mutator do not change state: accessor Accessors need to be declared const required for passing by const reference 73
74
L10, 2009-11-30ID1218, Christian Schulte Initializer Lists In constructor after parameter list after colon: comma separated list in order of declaration of members Only initialize, avoid initialization with subsequent assignment 74
75
L10, 2009-11-30ID1218, Christian Schulte Copying and Assignment Copying is controlled by copy constructor IntCell(const IntCell& c) : x(c.x) {} Assignment is controlled by assignment operator IntCell& operator=(const IntCell& c) { if (this != &c) x=c.x; return *this; } These are synthesized by compiler if missing required for resource management 75
76
L10, 2009-11-30ID1218, Christian Schulte Destructor ~IntCell() { delete x; } When object is deleted by delete (for heap allocated) by going out of scope (for automatically allocated) destructor is invoked for resource management 76
77
L10, 2009-11-30ID1218, Christian Schulte Default Constructor A constructor with no arguments (or all arguments with default values) automatically generated, if no constructors provided Important for initialization IntCell c; invokes the default constructor 77
78
L10, 2009-11-30ID1218, Christian Schulte Example Find three mistakes and correct class A { private: int* x; public: A() : x(new int[1]) {} ~A() { delete x; } int val() { return *x; } A(const A& a) : x(new int[1]) { *x = a.val(); } A& operator=(const A& a) { delete [] x; x = new int[1]; *x=a.val(); return *this; } }; 78
79
L10, 2009-11-30ID1218, Christian Schulte Example Find three mistakes and correct class A { private: int* x; public: A() : x(new int[1]) {} ~A() { delete x; } int val() { return *x; } A(const A& a) : x(new int[1]) { *x = a.val(); } A& operator=(const A& a) { delete [] x; x = new int[1]; *x=a.val(); return *this; } }; const missing! 79
80
L10, 2009-11-30ID1218, Christian Schulte Example Find three mistakes and correct class A { private: int* x; public: A() : x(new int[1]) {} ~A() { delete x; } int val() { return *x; } A(const A& a) : x(new int[1]) { *x = a.val(); } A& operator=(const A& a) { delete [] x; x = new int[1]; *x=a.val(); return *this; } }; must be: delete [] x 80
81
L10, 2009-11-30ID1218, Christian Schulte Example Find three mistakes and correct class A { private: int* x; public: A() : x(new int[1]) {} ~A() { delete x; } int val() { return *x; } A(const A& a) : x(new int[1]) { *x = a.val(); } A& operator=(const A& a) { delete [] x; x = new int[1]; *x=a.val(); return *this; } }; test for self-assignment missing 81
82
L10, 2009-11-30ID1218, Christian Schulte Example What is the value of z? class A { public: int x; A() : x(7) {} A(int y) : x(y+4) {} A(const A& a) : x(a.x-1) {} A& operator=(const A& a) { x = a.x+3; return *this; } }; A a(4); A b; A c(a); b = c; int z = b.x; a.x = 8, c.x = 7, b.x = 10 82
83
Summary: Fine Points for Objects L10, 2009-11-30ID1218, Christian Schulte 83
84
L10, 2009-11-30ID1218, Christian Schulte Static Members Static member is part of class, not of instance maintain data that is shared among all instances of a class Requires declaration and definition Declaration use keyword static done in header Definition use class name done in implementation 84
85
L10, 2009-11-30ID1218, Christian Schulte Namespaces Organize multiple functions, classes, etc together namespace N {… } Inside the namespace, as always C Outside namespace N::C Convenience: make available single class using N::C; namespace using namespace N; Reference to C in global namespace ::C 85
86
Summary: Inheritance L10, 2009-11-30ID1218, Christian Schulte 86
87
L10, 2009-11-30ID1218, Christian Schulte Static versus Dynamic Dispatch Static dispatch: use compile-time type of reference to object default behavior in C++ Dynamic dispatch: use runtime type for finding member function default behavior in Java in C++: mark member functions as virtual important case: virtual destructor 87
88
L10, 2009-11-30ID1218, Christian Schulte Defaults with Inheritance Copy constructor invokes copy constructor on base classes invokes copy constructor on newly added data members Assignment operator invokes assignment operator on base classes invokes assignment operator on newly added data members Destructor invokes destructors on newly added data members invokes destructors on base classes 88
89
L10, 2009-11-30ID1218, Christian Schulte Abstract Methods and Classes Member functions can be declared abstract in base class declare as virtual declaration followed by = 0; Must be implemented in inheriting classes instance creation only for-non abstract classes possible 89
90
L10, 2009-11-30ID1218, Christian Schulte Type Conversions Assume we know that p is a student, really Person* p = new Student(123,"Eva",2); Use dynamic cast Student* s = dynamic_cast (p); performs check and cast at runtime returns NULL, if not a Student 90
91
L10, 2009-11-30ID1218, Christian Schulte Example What is the value of z? class A { public: virtual int x() { return 1; } int y() { return -1; } }; class B : public A { public: virtual int x() { return 6; } }; class C : public B { public: int y() { return 3; } }; class D : public B { public: virtual int x() { return B::x()+8; } }; C* c = new C(); D* d = new D(); int z = c->y()+dynamic_cast (d)->x()+ dynamic_cast (c)->y(); dynamic_cast (d)->x() use dynamic dispatch and returns 6+8=14 dynamic_cast (c)->y() uses static dispatch and returns -1 91
92
Summary: C Programming L10, 2009-11-30 92 ID1218, Christian Schulte
93
L10, 2009-11-30ID1218, Christian Schulte Major Differences… No classes use structs (see later) No references use pointers No overloading No templates No default parameters All local variable declarations must be at beginning of function Memory management Libraries 93
94
L10, 2009-11-30ID1218, Christian Schulte The Struct Type Combine data into one structure struct IntPair { int x; int y; }; Also available in C++, corresponds to class IntPair { public: int x; int y; }; 94
95
L10, 2009-11-30ID1218, Christian Schulte Preprocessor Macros Conditional compilation Textual substitution #define FOOVALUE 1 Macros #define max(x,y) (x>y?x:y) unsafe! unsafe! things go wrong b = max(a--,c--); 95
96
L10, 2009-11-30ID1218, Christian Schulte C-Style Memory Management Allocate n bytes from heap void* malloc(size_t n); Free memory block p obtained by malloc void free(void* p); Never mix new+delete with malloc+free never use delete on malloc block and vice versa 96
97
Outlook L10, 2009-11-30 97 ID1218, Christian Schulte
98
Outlook Discussion functional programming concurrent programming object-oriented programming imperative programming system programming Course summary L10, 2009-11-30ID1218, Christian Schulte 98
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.