1 / 98

C++: Memory Management, Summary

Christian Schulte cschulte@kth.se Software and Computer Systems School of Information and Communication Technology KTH – Royal Institute of Technology Stockholm, Sweden. C++: Memory Management, Summary. ID1218 Lecture 10 2009-11-30. Overview. Memory management case studies

aderyn
Télécharger la présentation

C++: Memory Management, Summary

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Christian Schulte cschulte@kth.se Software andComputer Systems School of Information and Communication Technology KTH – Royal Institute of Technology Stockholm, Sweden C++: Memory Management, Summary ID1218 Lecture 10 2009-11-30

  2. Overview • Memory management case studies • resizable arrays • freelists • reference counting • Summary C and C++ • summary… • … and questions you should be able to answer ID1218, Christian Schulte

  3. Memory Management Case studies 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 ID1218, Christian Schulte

  5. Resizable Arrays 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 ID1218, Christian Schulte

  7. Resizable Arrays • Members • current size: unsigned int • element array: *Element • First attempt for integers • make polymorphic in last step ID1218, Christian Schulte

  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 inti) const; void set(unsigned inti, int x); ~IRA(); }; ID1218, Christian Schulte

  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 ID1218, Christian Schulte

  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 ID1218, Christian Schulte

  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]) {} ID1218, Christian Schulte

  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 ID1218, Christian Schulte

  13. Destructor IRA::~IRA() { delete [] _x; } • Design: nothing shared between copies ID1218, Christian Schulte

  14. Assignment Operator IRA& IRA::operator=(const IRA& ira) { if (this != &ira) { delete [] _x; _n = ira._n; _x = new int[_n]; for (unsigned inti=0; i<_n; i++) _x[i] = ira._x[i]; } return *this; } • Design: nothing shared between copies ID1218, Christian Schulte

  15. Access inline int IRA::get(unsigned inti) const { return _x[i]; } inline void IRA::set(unsigned inti, int x) { _x[i]=x; } • Must go into header file ID1218, Christian Schulte

  16. Access: Assert Proper Use inline int IRA::get(unsigned inti) const { assert(i < _n); return _x[i]; } inline void IRA::set(unsigned inti, int x) { … } • Checked at runtime • requires #include <cassert> • runtime error, if violated (can be looked for in debugger) • ignored, if the macro NDEBUG is defined • pass –DNDEBUG from commandline ID1218, Christian Schulte

  17. Resizing the Array void IRA::resize(unsigned int n) { int* x = new int[n]; unsigned int m = std::min(n,_n); for (unsigned inti=0; i<m; i++) x[i] = _x[i]; delete [] _x; _n = n; _x = x; } • std::min requires #include <algorithm> ID1218, Christian Schulte

  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 inti); ~IRA(); }; ID1218, Christian Schulte

  19. Overloading []: First Attempt inline int IRA::operator[](unsigned inti) { 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 ID1218, Christian Schulte

  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 inti); const int& operator[](unsigned inti) const; ~IRA(); }; ID1218, Christian Schulte

  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 ID1218, Christian Schulte

  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 ID1218, Christian Schulte

  23. Generic Resizable Arrays template <typename T> class RA { private: unsigned int _n; T* _x; public: RA(unsigned int n=8); RA(const RA<T>& ra); RA<T>& operator=(const RA<T>& ra); void resize(unsigned int n); T& operator[](unsigned inti); const T& operator[](unsigned inti) const; ~RA(); }; ID1218, Christian Schulte

  24. Generic Copy Constructor template <typename T> RA<T>::RA(const RA<T>& ra) : _n(ra._n), _x(new T[_n]) { for (unsigned inti=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! ID1218, Christian Schulte

  25. Mixing With Normal Arrays RA<int> x(42); void f(int* a); void g(int a[]); f(x); g(x); • Both calls do not work: x is of type RA<int> • Simple solution: f(&x[0]); g(&x[0]); ID1218, Christian Schulte

  26. Mixing With Normal Arrays template <typename T> class RA { … public: … operator T*(void) { return _x; } }; • Dangerous… RA<int> x(42); int* y = x; x.resize(1024); y[0] = 4; ID1218, Christian Schulte

  27. Freelists 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 ID1218, Christian Schulte

  29. Integer Lists class IL { private: int _hd; IL* _tl; public: IL(int h, IL* t = NULL); inthd() 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 ID1218, Christian Schulte

  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; } ID1218, Christian Schulte

  31. Overloading Memory Allocation #include <cstdlib> class IL { private: int _hd; IL* _tl; public: IL(int h, IL* t = NULL); inthd() 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); }; ID1218, Christian Schulte

  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 ID1218, Christian Schulte

  33. Freelist as Static Member #include <cstdlib> class IL { private: int _hd; IL* _tl; static IL* _free; public: IL(int h, IL* t = NULL); inthd() 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(); }; ID1218, Christian Schulte

  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! ID1218, Christian Schulte

  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; } ID1218, Christian Schulte

  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 ID1218, Christian Schulte

  37. Deallocating to the Freelist inline void IL::operator delete(void* p) { IL* il = static_cast<IL*>(p); il->_tl = _free; _free = il; } ID1218, Christian Schulte

  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… ID1218, Christian Schulte

  39. Reference Counting 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? ID1218, Christian Schulte

  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 ID1218, Christian Schulte

  42. Array Object Proper class AO { public: unsigned int n; int* x; unsigned int rc; }; ID1218, Christian Schulte

  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 inti); … }; ID1218, Christian Schulte

  44. Array Handle Constructor AH::AH(unsigned int n) : _ao(new AO) { _ao->n = n; _ao->x = new int[n]; _ao->rc = 1; } ID1218, Christian Schulte

  45. Array Handle: Object Access inline int& AH::operator[](unsigned int i) { return _ao->x[i]; } … ID1218, Christian Schulte

  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 ID1218, Christian Schulte

  47. Copy Constructor inline AH::AH(const AH& ah) : _ao(ah._ao) { _ao->rc++; } • Array object is used by one additional handle ID1218, Christian Schulte

  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 ID1218, Christian Schulte

  49. Putting the Object at its Place… class AH { private: class AO { public: unsigned int n; int* x; unsigned intrc; }; AO* _ao; public: AH(unsigned int n=8); … }; • Object should never be used without controlling handle ID1218, Christian Schulte

  50. Smart Pointers • Generic wrapper class overloading operators -> and * • Part of C++ standard library • Use reference counting inside ID1218, Christian Schulte

More Related