Memory Management Lecture Notes PDF
Document Details
Uploaded by FervidDune
ETH Zurich
Tags
Summary
These lecture notes cover memory management concepts in C++. Topics include dynamic data structures, stacks, and linked lists, along with the use of new, delete, and destructors. C++ programming principles are highlighted throughout the text.
Full Transcript
21. Memory Management 535 Problem Last week: dynamic data structure our_list Have allocated dynamic memory, but not released it again. In particular: no functions to remove elements from our_list. Today: correct memory management with new and delete with help of the (simple...
21. Memory Management 535 Problem Last week: dynamic data structure our_list Have allocated dynamic memory, but not released it again. In particular: no functions to remove elements from our_list. Today: correct memory management with new and delete with help of the (simpler) dyanmic data structure stack. 536 Goal: class stack with memory management class stack { public: // post: Push an element onto the stack void push(int value); // pre: non-empty stack // post: Delete top most element from the stack void pop(); // pre: non-empty stack // post: return value of top most element int top() const; // post: return if stack is empty bool empty() const;... 537 Recall the Linked List element (type lnode) 1 5 6 value (type int) next (type lnode*) struct lnode { int value; lnode* next; // constructor lnode(int v, lnode* n) : value(v), next(n) {} }; 538 Stack = Pointer to the Top Element element (type lnode) 1 5 6 value (type int) next (type lnode*) class stack { public: void push(int value);... private: lnode* topn; }; 539 Empty Stack class stack { public: stack() : topn(nullptr) {} // default constructor void push(int value); void pop(); int top() const; bool empty() const; private: lnode* topn; } 540 empty(), top() // POST: Returns true if stack is empty, false otherwise bool stack::empty() const { } // PRE: Stack must be non-empty // POST: Returns the stack's top value int stack::top() const { } 541 empty(), top() // POST: Returns true if stack is empty, false otherwise bool stack::empty() const { return topn == nullptr; } // PRE: Stack must be non-empty // POST: Returns the stack's top value int stack::top() const { } 541 empty(), top() // POST: Returns true if stack is empty, false otherwise bool stack::empty() const { return topn == nullptr; } // PRE: Stack must be non-empty // POST: Returns the stack's top value int stack::top() const { assert(!empty()); } 541 empty(), top() // POST: Returns true if stack is empty, false otherwise bool stack::empty() const { return topn == nullptr; } // PRE: Stack must be non-empty // POST: Returns the stack's top value int stack::top() const { assert(!empty()); return topn->value; } 541 empty(), top() // POST: Returns true if stack is empty, false otherwise bool stack::empty() const { return topn == nullptr; } // PRE: Stack must be non-empty // POST: Returns the stack's top value int stack::top() const { assert(!empty()); return topn->value; } reminder: shortcut for (*topn).value 541 Recall the new Expression underlying type new T(...) new-Operator constructor arguments Effect: memory for a new object of type T is allocated...... and initialized by means of the matching constructor Value: address of the new T object, Type: Pointer T*! 542 The new Expression push(4) void stack::push(int value) { topn = new lnode(value, topn); } topn 1 5 6 543 The new Expression push(4) Effect: new object of type T is allocated in memory... void stack::push(int value) { topn = new lnode(value, topn); } topn 1 5 6 543 The new Expression push(4) Effect: new object of type T is allocated in memory...... and intialized by means of the matching constructor void stack::push(int value) { topn = new lnode(value, topn); } topn 4 1 5 6 543 The new Expression push(4) Effect: new object of type T is allocated in memory...... and intialized by means of the matching constructor Value: address of the new object void stack::push(int value) { topn = new lnode(value, topn); } topn 4 1 5 6 543 The delete Expression Objects generated with new have dynamic storage duration: they “live” until they are explicitly deleted 544 The delete Expression Objects generated with new have dynamic storage duration: they “live” until they are explicitly deleted delete expr type void delete-Operator pointer of type T*, pointing to an object that had been created with new. 544 The delete Expression Objects generated with new have dynamic storage duration: they “live” until they are explicitly deleted delete expr type void delete-Operator pointer of type T*, pointing to an object that had been created with new. Effect: object is deconstructed (explanation below)... and memory is released. 544 The delete Expression Objects generated with new have dynamic storage duration: they “live” until they are explicitly deleted delete expr type void delete-Operator pointer of type T*, pointing to an object that had been created with new. Effect: object is deconstructed (explanation below)... and memory is released. Attention: delete does not set the pointer to nullptr 544 Who is born must die... Guideline “Dynamic Memory” For each new there is a matching delete! 545 Who is born must die... Guideline “Dynamic Memory” For each new there is a matching delete! Non-compliance leads to memory leaks 545 Who is born must die... Guideline “Dynamic Memory” For each new there is a matching delete! Non-compliance leads to memory leaks Unused objects that occupy memory... 545 Who is born must die... Guideline “Dynamic Memory” For each new there is a matching delete! Non-compliance leads to memory leaks Unused objects that occupy memory...... until it is eventually all used up (heap overflow) 545 Careful with new and delete! rational* t = new rational; rational* s = t; delete s; int nominator = t->denominator(); 546 Careful with new and delete! rational* t = new rational; memory for t is allocated rational* s = t; delete s; int nominator = t->denominator(); 546 Careful with new and delete! rational* t = new rational; memory for t is allocated rational* s = t; other pointers may point to the same object delete s; int nominator = t->denominator(); 546 Careful with new and delete! rational* t = new rational; memory for t is allocated rational* s = t; other pointers may point to the same object delete s;... and used for releaseing the object int nominator = t->denominator(); 546 Careful with new and delete! rational* t = new rational; memory for t is allocated rational* s = t; other pointers may point to the same object delete s;... and used for releaseing the object int nominator = (*t).denominator(); error: memory released! Dereferencing of „dangling pointers” Pointer to released objects: dangling pointers 546 Careful with new and delete! rational* t = new rational; memory for t is allocated rational* s = t; other pointers may point to the same object delete s;... and used for releaseing the object int nominator = (*t).denominator(); error: memory released! Dereferencing of „dangling pointers” Pointer to released objects: dangling pointers Releasing an object more than once using delete is a similar severe error 546 Stack Continued: pop() topn 1 5 6 547 Stack Continued: pop() void stack::pop() { assert(!empty()); lnode* p = topn; topn = topn->next; delete p; } topn 1 5 6 547 Stack Continued: pop() void stack::pop() { assert(!empty()); lnode* p = topn; topn = topn->next; delete p; } topn 1 5 6 p 547 Stack Continued: pop() void stack::pop() { assert(!empty()); lnode* p = topn; topn = topn->next; delete p; } topn 1 5 6 p 547 Stack Continued: pop() void stack::pop() { assert(!empty()); lnode* p = topn; topn = topn->next; delete p; } topn 1 5 6 p 547 Zombie Elements { stack s1; // local variable s1.push(1); s1.push(2); s1.push(3); std::cout