Presentation is loading. Please wait.

Presentation is loading. Please wait.

. Smart Pointers. Memory Management u One of the major issues in writing C/C++ code is managing dynamically allocated memory u Biggest question is how.

Similar presentations


Presentation on theme: ". Smart Pointers. Memory Management u One of the major issues in writing C/C++ code is managing dynamically allocated memory u Biggest question is how."— Presentation transcript:

1 . Smart Pointers

2 Memory Management u One of the major issues in writing C/C++ code is managing dynamically allocated memory u Biggest question is how to ensure that allocated memory will be freed when it is no longer in use

3 Strategy #1: Fixed Ownership u Allocated pointer belongs to the entity (function or objects) that created it u That entity is responsible for freeing the pointer void foo() { char* mem = new char[1000]; … delete [] mem; }

4 Example: String class class String { public: String( char const *str ) { int l = strlen(str); m_data = new char[l]; memcpy(m_data, str, l); } ~String() { delete [] m_data; } private: char* m_data; };  The memory for char* represented by String is owned by the object u Class encapsulates details of memory management u With careful implementation, this class is memory-tight

5 Strategy #2: Dynamic ownership (compile time) u Object has an owner u However, owner changes through specific function calls Example: u strdup(s) allocates new memory and transfers it with return value u strdup does not release the memory

6 Ownership transfer and interface design Design principle: u keep free resources at the same level you allocate them u Reduces memory leaks due to interface problems

7 Example: design choices ReadLine – read a line of input u char* ReadLine() – returns pointer to newly allocated memory – user has to free it u char* ReadLine() – returns pointer to static buffer – user has to copy line to another buffer u void ReadLine(char* Buffer) – uses a user supplied buffer – ReadLine cannot resize buffer

8 Strategy #3: Dynamic ownership (run time) u In some case we cannot know who will own a pointer u In other cases, we do not want the programmer to remember who owns what u Can we use an object that “remembers” who owns the object?

9 Dumb Pointers u Suppose T is a class u T* is a “dumb pointer” supplied by compiler u It remembers the address of the object and allows us to access it, but nothing else u Can we build smarter pointers?

10 The Pointer Interface To implement a pointer-like object we need: u pointer::pointer( T*) u pointer::pointer( pointer const& ) u pointer& operator=( pointer const& ) u T& pointer::operator*() u T const& pointer::operator*() const u T* pointer::operator->() u T const * pointer::operator->() const u pointer::operator void const*() const

11 Pointer class template class pointer { public: pointer( T* p = NULL ) : m_ptr(p) {} T& operator*() { return *m_ptr; } … private: T* m_ptr; };

12 “Smart” Pointers u We can ensure that pointer “cleans up” after itself u Simply add destructor pointer::~pointer() { if( m_ptr != NULL ) delete m_ptr; }  This class is called auto_ptr

13 Auto_ptr struct bar { … }; void foo() { auto_ptr myBar = new bar; … // use myBar as a pointer … } // myBar is deleted automatically

14 Auto_ptr in exceptions u Auto_ptrs provide clean mechanism to deal with exception void foo() { auto_ptr myBar = new bar; apple(); // apple might throw an execption … } // myBar is deleted automatically // even if an exception is thrown by apple

15 Auto_ptr auto_ptr is like a pointer, but not exactly: void foo() { auto_ptr myBar = new bar; … if( … ) { auto_ptr myOtherBar = myBar; … } … } What happens in this example?

16 Transfer of Ownership u To avoid multiple deletes, auto_ptr ensures that only one auto_ptr points to a certain object u The statement auto_ptr myOtherBar = myBar; transfer the ownership from myBar to myOtherBar  How do we achieve this?

17 auto_ptr details auto_ptr( auto_ptr& rhs ) : m_ptr( rhs.release() ) {} auto_ptr& operator=( auto_ptr& rhs ) { reset( rhs.release() ); return *this; } void reset(T* p = NULL) { if( m_ptr != p ) delete m_ptr; m_ptr = p; } T* release() { T* tmp = m_ptr; m_ptr = NULL; return tmp; }

18 Auto_ptr summary u Provide mechanism for transfer of ownerships u Can be dangerous u Requires discipline from programmer u Does not replace the need for pointers  The method T* auto_ptr ::get() allows to access the dumb pointer version of an auto_ptr

19 Strategy #4: Reference Counting u In some cases, we do not want to establish ownership u Managing ownership within forces us to make unnecessary copies u Can we get away with memory management without authorship? u The general mechanism of reference counting provides one solution

20 Reference Counting String a = “foo bar”; String b = a; String c = a; The resulting memory structure: foo bar a: b: c: stackheap

21 Reference counting u Can we do better? Idea: Do not copy value of string u Have all object point to the same memory u How do we know when to free the memory? foo bar a: b: c:

22 Reference Counting Solution: u Store a reference counter that counts number of pointers u Reference counter shows whether the object is in use a: b: c: 3 foo bar

23 Reference Counting 1 After Object Creation 1 1 After Object Destruction 3 0 After Last Object Destruction 4 2 After Object Copy 2

24 String with reference counting u See [String.h]

25 Example revisited Returning to the ReadLine example u String ReadLine()  returns a String object  A new String is copied on return value  But… the actual memory is not copied  Ownership transfer occur smoothly with minimal overhead

26 ReadLine Example String ReadLine() { String line; … // do read return line; } void foo() { String a = ReadLine(); … }

27 General Purpose Reference Counting u See RCPointer.h

28 Reference Counting u Suppose String has operator[] u Consider the following code String a = “foo bar”; String b = a; String c = a; c[2] = ‘l’; u What does this code do?

29 Reference Counting u After we modify c, it is no longer identical to a and b u We can no longer save memory by storing all three strings in one place Solution u “Clone on Write” – make a copy of an object when it is modified

30 Implementing operator[] in String Read-only access: char const& operator[](int i) const { return m_ptr->m_data[i]; } Read/Write access: char & operator[](int i) { if( m_ptr->m_rc > 1 ) { // make a new copy of the string m_ptr->m_rc--; m_ptr = new StringValue( *m_ptr ); } return m_ptr->m_data[i]; }

31 Clone on Write u Perform the copy operation only when new copy is needed u This is an instance of “lazy evaluation” u How can we perform this in a generic RCPointer?

32 Template Clone on Write Distinguish between u read only access: T const& RCPointer ::operator*() const; T const* RCPointer ::operator->() const; u and read/write access T& RCPointer ::operator*(); T* RCPointer ::operator->(); In these operations we perform copy

33 Reference counting and cycles u Reference counting could have been used as an automatic garbage collection in C++. u Problem: Data structures can include cycles. In this case the pointers will never be deleted. If all these pointers were reference counted, then no memory would be freed

34 When to use what ? u auto_ptr/Ownership transfer:  simple yet problematic. Good for local variables u Reference counting:  Simple, memory safe, efficient, problematic when modifying the object.  Very good for large objects, and STL containers providing these do not change the objects. u Reference counting with Clone On Write:  Optimal for STL, and for large objects. problematic for data structures with cycles.


Download ppt ". Smart Pointers. Memory Management u One of the major issues in writing C/C++ code is managing dynamically allocated memory u Biggest question is how."

Similar presentations


Ads by Google