Your Federal Quarterly Tax Payments are due April 15th Get Help Now >>

Memory Management by alendar

VIEWS: 120 PAGES: 11

Memory Management

More Info
									Memory Management                                  

          31 / 31
          Memory Management
          Week 8

          Chapter Goals
               To learn the different categories of memory
               To understand how to avoid common memory management errors
               To learn to write and use constructors and destructors
               To be able to create classes that manage their own memory allocation and deallocation

          18.1 Categories of Memory
               Memory is divided into four categories:
                 1. Code - instructions for all global and member functions
                 2. Static Data - global variables, and all local and member variables declared static
                 3. Run-time Stack - automatics (local non-static)
                 4. Free Store (Heap) - dynamically allocated (new)

          18.1.1 Code Memory
               Contains all machine instructions for functions and methods
               May be referenced through pointers
                    (See next chptr. and Lippman[1] for discussion on function pointers)

          18.1.2 Static Data Memory
               Globals, static locals and static member variables
               Size of statics can be known prior to execution
               Created only once
               Initialized only once, before main

          18.1.3 The Run-time Stack
               Used for functions
               Every call is a new activation record on stack
               Activation record contains:
                     Return pointer
                     Local variables
                     Other machine-specific stuff
               Return from function decrements stack pointer
                     Local variables cease to exist when function exits
                     Size of locals must be known at compile time

1 of 11                                                                                                       15/8/06 9:51 AM
Memory Management                                   

          18.1.4 The Run-time Stack (example)
          If function f has called g, which, in turn,
          called h, then the stack looks something
          like this:

          Heap Memory
          The heap, or free store:

                Request storage area with new
                Values accessed through a pointer
                Neither the number of values, nor the size of a particular value need be known at compile time
                Lifetime of a value is not tied to a function
                Values may persist after program ends
                Space returned to heap using delete

          18.2 Common Memory Errors
                The programmer is responsible for memory management in C++
                Pointers can refer to memory in any of the four areas (above)
                Possible errors include:
                      Using a value that has not been initialized
                      Using a pointer to reference a memory location that is no longer valid (dangling pointer)
                      Forgetting to delete a dynamically allocated section of memory (memory leak)
                      Deleting a memory value that was never allocated
                      Deleting a dynamically allocated section of memory more than once

          18.3 Constructors (Revision)
                Same name as the class

2 of 11                                                                                                        15/8/06 9:51 AM
Memory Management                                 

               No return type
               Used to initialize class' attributes
               May be overloaded
               Only one constructor is invoked at creation
               Implicitly invoked:
                     Each time a block is entered where an object is declared
                     For static objects - before main starts
                     When an object is created on the heap with new
                     When an object is passed by value
                     For member objects, when aggregate is created
                     When object from derived class is instantiated

          18.3 Constructors - String Example
          E.g., String class, with underlying array on heap.

          class String
             String(); // Default constructor
             String(const char p[]); // Simple constructor
             String(const String& right); // Copy constructor
             ~String(); // Destructor
             String& operator=(const String& right); // Assignment op
             String& operator+=(const String& right);
             int length() const;
             char& operator[](int index);
             char operator[](int index) const;
             char* buffer;
             int len;

          18.3.1 Constructors with Arguments
               All constructors perform necessary initialization
               Example: Our constructor must allocate space from heap and initialize:

               String::String(const char p[])
               // Determine number of characters in string (strlen(p))
                  len = 0;
                  while (p[len] != '\0')
               // Allocate buffer array,
               // remember to make space for NULL character
                  buffer = new char[len + 1];
               // Copy new characters (strcpy( buffer, p ))
                  for (int i = 0; i < len; i++)
                     buffer[i] = p[i];
                  buffer[len] ='\0';

          18.3.2 Default Constructors
               The constructor that takes no arguments
               Invoked without parenthesis, (except for unnamed temporaries

3 of 11                                                                                                      15/8/06 9:51 AM
Memory Management                                 

                    When a variable is declared (or created from the heap) with no arguments
                    The only initializer for elements in an array
                    When object is member data of another class, and no initializer is provided

          18.3.2 Default Constructors (cont.)
               Example: a String is, by default, an empty string

                  len = 0;
                  buffer = NULL; // No need to allocate array
                                 // to hold zero characters

          18.3.3 Copy Constructors
               Sole parameter is a const reference to an object of the same class
               Automatically supplied by compiler - memberwise (shallow) copy by default
               Calls copy constructor of all member data
               Used to copy (clone) a value

          18.3.3 Copy Constructors (cont.)
               Example: each String has its own dynamically allocated buffer, so default behavior is
               insufficient. We extend this behavior:

               String::String(const String& right)
                  int n = right.length();
                  buffer = new char[n + 1];
                  for (int i = 0; i < n; i++)
                     buffer[i] = right[i];
                  buffer[n] = '\0';

          18.3.3 Copy Constructors (cont.)


               String first("Fred");
               String second(first);
               // second is initialized from first
               // using copy constructor

               During initialization using =

               String third = first; // Also uses copy constructor

               When an object is passed by value
                   Note: Use const when passing a reference to avoid copy overhead

4 of 11                                                                                                      15/8/06 9:51 AM
Memory Management                                    

          18.3.4 Field Initializer Lists
          Member data may be assigned in a field initializer list.

                Syntax only valid for constructors
                Used to avoid modifying an attribute twice (default constructor, then in the body of the outer

          class Employee
             Employee(String employee_name, double initial_salary);
             . . .
             String name;
             double salary;

          Employee::Employee(String employee_name, double initial_salary)
             : name(employee_name), salary(initial_salary)

          18.3.4 Field Initializer Lists (cont.)
                Necessary to invoke base-class constructors; otherwise, the base-class' default constructor will
                be called:

          class TeachingAssistant : public Employee
             TeachingAssistant(String student_name);

          TeachingAssistant::TeachingAssistant(String student_name)
             // Teaching assistants all get same starting salary
             : Employee(student_name, 5000)

          18.3.4 Field Initializer Lists (cont.)
                Initializer lists must be used for:
                       Data fields declared as non-static const
                       To invoke a base class' constructor (other than default)
                E.g., necessary when assigning a size to a vector member:

                class PartDescription
                   PartDescription(String part_name,
                      int inventory_number);
                   const String name;
                   const int part_number:
                   vector<PartDescription*> subcomponents;

5 of 11                                                                                                         15/8/06 9:51 AM
Memory Management                               


              PartDescription::PartDescription(String part_name,
                    int inventory_number)
                 : name(part_name), part_number(inventory_number),
                    subcomponents(3) {}

          18.3.5 Assignment Operators
              Tasks performed are similar to copy constructor
              Must do cleanup first
              Check for auto-assignment
              Example: String class:

              String& String::operator=(const String& right)
                 if (this != &right)
                    delete[] buffer; // Get rid of old buffer
                    len = right.length();
                    buffer = new char[len + 1];
                    for (int i = 0; i < len; i++)
                       buffer[i] = right[i];
                    buffer[len] = '\0';
                 return *this;

          18.4 Destructors
              Perform necessary housekeeping tasks
              Named ~ClassName, no arguments, no return type
              Implicitly called on:
                    Local variables, at end of block
                    Parameters, at end of function
                    Temporary variables, at end of statement
                    Heap values, when delete is called
                    Static values, when main terminates
                    Member data, when object is deallocated
                    Base class object, when derived class object is deallocated
                    Local variables, when an exception is thrown and execution leaves the block

          18.4 Destructors (cont.)

          Syntax 17.2 : Overloading Operator Definition


6 of 11                                                                                                    15/8/06 9:51 AM
Memory Management                                  

                             delete[] buffer;

           Purpose: Perform any housekeeping tasks that should be performed before an object is deleted.

          18.4 Virtual Destructors (cont.)
               Make destructors for base classes virtual
               E.g.: Consider the following declarations

               class Employee
               { virtual ~Employee(); };

               { cout << "Goodbye Employee\n"; }

               class TeachingAssistant : public Employee
               { ~TeachingAssistant(); };

               { cout << "Goodbye TeachingAssistant\n"; }

               Now consider the following:

               Employee *a = new TeachingAssistant();
               delete a;

          18.4 The Big 3
          The "Big 3":

            1. Copy constructor
            2. Assignment operator
            3. Destructor

               All have default behavior, as does the default constructor
               Behavior sometimes needs to be extended
               Reason to define one => reason to define all 3 (or all 4)
               Build all 3 on lower-level helper methods

          18.4.1 The Class auto_ptr
               "Smart pointers"
               Declared in <memory>
               Good when the lifetime of the dynamic value is tied to another object
               Dynamic memory auto_ptr references is automatically recovered
               Very useful with exceptions

          See also: Advanced Topic 18.2 - Overloading the memory management operators.

          18.5 Reference Counting

7 of 11                                                                                                       15/8/06 9:51 AM
Memory Management                                  

               Simple rule: objects that allocate memory should clean it up

               Not usually that simple. Consider sharing:
               Two options:
                 1. Designate one as owner (not always possible)
                 2. Use reference counting

          18.5 Reference Counting
               Store reference count with the shared resource

               New object has reference count of 1:

               When data object is shared, reference count is incremented:

          18.5 Reference Counting (cont.)
               When a references is destroyed (or reassigned), ref count is decremented:

               When the reference count is zero, the shared resource is deleted

          18.5 Example: Reference Counting
          Consider our String class: change the semantics for the assignment of strings so that two strings
          would share a common internal data buffer:

               Structure holding reference count and the buffer is moved to a nested class,
               References are managed by reassign
                     Takes ptr to a StringReference
                     If not NULL, reference to argument value is incremented
                     Reference to current value is decremented
                     If current reference is 0, object is deleted
                     Current object is set to refer to argument value
               See sharedString.cpp


                1   #include <iostream>
                3   using namespace std;
                5   class SharedString
                6   {

8 of 11                                                                                                       15/8/06 9:51 AM
Memory Management                    

             7      public:
             8          SharedString();
             9          SharedString(const char* right);
            10          SharedString(const SharedString& right);
            11          ~SharedString();
            12          SharedString& operator=(const SharedString&);
            13      private:
            14          class StringReference;
            15          StringReference* p;
            16          void reassign(StringReference*);
            17      };
            19      class SharedString::StringReference
            20      {
            21      public:
            22         int count;
            23         char* buffer;
            24         StringReference(const char* right);
            25         ~StringReference();
            26      };
            28      SharedString::SharedString() : p(NULL)
            29      {
            30         cout << "Entering SharedString() \n";
            31      }
            33      SharedString::SharedString(const char* right) : p(NULL)
            34      {
            35         reassign(new StringReference(right));
            36      }
            38      SharedString::SharedString(const SharedString& right) : p(NULL)
            39      {
            40         reassign(right.p);
            41      }
            43      SharedString::~SharedString()
            44      {
            45         reassign(NULL);
            46      }
            48      SharedString& SharedString::operator=(const SharedString& right)
            49      {
            50         reassign(right.p);
            51         return *this;
            52      }
            54      void SharedString::reassign(StringReference* np)
            55      {
            56         if (np != NULL) // Increment count on the new value
            57            np->count += 1;
            58         if (p != NULL) // Decrement reference counts on old value
            59         {
            60            p->count -= 1;
            61            if (p->count == 0)
            62               delete p;
            63         }
            64         p = np; // Change binding

9 of 11                                                                                         15/8/06 9:51 AM
Memory Management                                       

              65       }
              67       SharedString::StringReference::StringReference(const char* right)
              68       {
              69          count = 0;
              70          int n = 0;
              71          while (right[n] != '\0')
              72             n++;
              73          buffer = new char[1 + n];
              74          for (int i = 0; i < n; i++)
              75             buffer[i] = right[i];
              76          buffer[n] = '\0';
              77       }
              79       SharedString::StringReference::~StringReference()
              80       {
              81          delete [] buffer;
              82       }
              84       SharedString g; // global value
              86       int main ( )
              87       {
              88               cout << "starting execution\n";
              89               cout << "SharedString a = \"Fred\";\n";
              90           SharedString a = "Fred";
              91               cout << "SharedString b = \"Alice\";\n";
              92           SharedString b = "Alice";
              93               cout << "SharedString c;\n";
              94           SharedString c;
              95               cout << "c = a;\n";
              96           c = a;
              97               cout << "a = b;\n";
              98           a = b;
              99               cout << "g = b;\n";
             100           g = b;
             101           cout << "return 0;\n";
             102           return 0;
             103       }

           18.5 Reference Counting

                   Create separate classes for; reference, shared data
                   Reference count in shared data object
                   Reference assignment: increment ref count
                   Reference destroyed: decrement ref count
                   Ref count reaches zero: destroy shared data


                   Beware of self-assignment
                   Avoid cycles

10 of 11                                                                                                           15/8/06 9:51 AM
Memory Management                                  

           Chapter Summary
            1. Memory is divided into four areas
            2. Pointers can refer to memory in any of the four areas
            3. Initialization errors can occur in any of the four area
            4. Stack-based memory is tied to function entry and exit
            5. Simple objects can be sliced. Use references or pointers
            6. Constructors tie memory allocation with object initialization. Copy constructors create copies
               of objects
            7. Destructors return resources when an object is deallocated. The "Big 3"
            8. Reference counts can be used to track shared resources

11 of 11                                                                                                      15/8/06 9:51 AM

To top