SunQuest
 
       C++
  Home arrow C++ arrow Page 10 - A Simple Garbage Collector for C++
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Dedicated Servers  
Actuate Whitepapers 
Moblin 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
C++

A Simple Garbage Collector for C++
By: McGraw-Hill/Osborne
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 4 stars4 stars4 stars4 stars4 stars / 41
    2005-06-21

    Table of Contents:
  • A Simple Garbage Collector for C++
  • Comparing the Two Approaches to Memory Management
  • Choosing a Garbage Collection Algorithm
  • What About auto_ptr?
  • An Overview of the Garbage Collector Classes
  • GCPtr In Detail
  • The Overloaded Assignment Operators
  • GCInfo
  • How to Use GCPtr
  • Allocating Arrays
  • A Larger Demonstration Program
  • Load Testing

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
    Iron Speed
     
    ADVERTISEMENT

    Stay one step ahead of the competition. Evaluate and give feedback on some of the hottest web development tools on the market today. Make your opinion heard! Click Here

    A Simple Garbage Collector for C++ - Allocating Arrays


    (Page 10 of 12 )

    If you are allocating an array using new, then you must tell GCPtr this fact by specifying its size when the GCPtr pointer to that array is declared. For example, here is the way to allocate an array of five doubles:

    GCPtr<double, 5> pda = new double[5];

    The size must be specified for two reasons. First, it tells the GCPtr constructor that this object will point to an allocated array, which causes the isArray field to be set to true. When isArray is true, the collect( ) function frees memory by using delete[ ], which releases a dynamically allocated array, rather than delete, which releases only a single object. Therefore, in this example, when pda goes out of scope, delete[ ] is used and all five elements of pda are freed. Ensuring that the correct number of objects are freed is especially important when arrays of class objects are allocated. Only by using delete[ ] can you know that the destructor for each object will be called.

    The second reason that the size must be specified is to prevent an out-of-bounds element from being accessed when an Iter is used to cycle through an allocated array. Recall that the size of the array (stored in arraySize) is passed by GCPtr to Iter’s constructor whenever an Iter is needed.

    Be aware that nothing enforces the rule that an allocated array be operated on only through a GCPtr that has been specified as pointing to an array. This is solely your responsibility.

    Once you have allocated an array, there are two ways you can access its elements. First, you can index the GCPtr that points to it. Second, you can use an iterator. Both methods are shown here.

    Using Array Indexing

    The following program creates a GCPtr to a 10-element array of ints. It then allocates that array and initializes it to the values 0 through 9. Finally, it displays those values. It performs these actions by indexing the GCPtr.

    // Demonstrate indexing a GCPtr.
    #include <iostream>
    #include <new>
    #include "gc.h"
    using namespace std;
    int main() {
     
    try {
        // Create a GCPtr to an allocated array of 10 ints.
       
    GCPtr<int, 10> ap = new int[10];
       
    // Give the array some values using array indexing.
        for(int i=0; i < 10; i++)
          ap[i] = i;
       
    // Now, show the contents of the array.
        for(int i=0; i < 10; i++)
          cout << ap[i] << " ";
       
    cout << endl;
     
    } catch(bad_alloc exc) {
        cout << "Allocation failure!\n";
        return 1;
     
    }
     
    return 0;
    }
    The output, with the display option off, is shown here:

    0 1 2 3 4 5 6 7 8 9

    Because a GCPtr emulates a normal C++ pointer, no array bounds checking is performed, and it is possible to overrun or under run the dynamically allocated array. So, use the same care when accessing an array through a GCPtr as you do when accessing an array through a normal C++ pointer.

    Using Iterators

    Although array indexing is certainly a convenient method of cycling through an allocated array, it is not the only method at your disposal. For many applications, the use of an iterator will be a better choice because it has the advantage of preventing boundary errors. Recall that for GCPtr, iterators are objects of type Iter. Iter supports the full complement of pointer operations, such as ++. It also allows an iterator to be indexed like an array.

    Here is the previous program reworked to use an iterator. Recall that the easiest way to obtain an iterator to a GCPtr is to use GCiterator, which is a typedef inside GCPtr that is automatically bound to the generic type T.

    // Demonstrate an iterator.
    #include <iostream>
    #include <new>
    #include "gc.h"
    using namespace std;
    int main() {
     
    try {
        // Create a GCPtr to an allocated array of 10 ints.  
        GCPtr<int, 10> ap = new int[10];
       
    // Declare an int iterator.
       
    GCPtr<int>::GCiterator itr;
       
    // Assign itr a pointer to the start of the array.
       
    itr = ap.begin();
       
    // Give the array some values using array indexing.
        for(unsigned i=0; i < itr.size(); i++)
          itr[i] = i;
       
    // Now, cycle through array using the iterator.
        for(itr = ap.begin(); itr != ap.end(); itr++)
          cout << *itr << " ";
       
    cout << endl;
     
    } catch(bad_alloc exc) {
       
    cout << "Allocation failure!\n";
       
    return 1;
      } catch(OutOfRangeExc exc) {
        cout << "Out of range access!\n";
        return 1;
     
    }
      return 0;
    }

    On your own, you might want to try incrementing itr so that it points beyond the boundary of the allocated array. Then try accessing the value at that location. As you will see, an OutOfRangeExc is thrown. In general, you can increment or decrement an iterator any way you like without causing an exception. However, if it is not pointing within the underlying array, attempting to obtain or set the value at that location will cause a boundary error.

    Using GCPtr with Class Types

    GCPtr is used with class types in just the same way it is used with built-in types. For example, here is a short program that allocates objects of MyClass:

    // Use GCPtr with a class type.
    #include <iostream>
    #include <new>
    #include "gc.h"
    using namespace std;
    class MyClass {
      int a, b;
    public:
      double val;
     
    MyClass() { a = b = 0; }
     
    MyClass(int x, int y) {
        a = x;
        b = y;
        val = 0.0;
     
    }
     
    ~MyClass() {
        cout << "Destructing MyClass(" <<
             a << ", " << b << ")\n";
      }
     
    int sum() {
        return a + b;
      }
     
    friend ostream &operator<<(ostream &strm, MyClass &obj);
    };
    // An overloaded inserter to display MyClass.
    ostream &operator<<(ostream &strm, MyClass &obj) {
      strm << "(" << obj.a << " " << obj.b << ")";
      return strm;
    }
    int main() {
      try {
        GCPtr<MyClass> ob = new MyClass(10, 20);
       
    // Show value via overloaded inserter.
        cout << *ob << endl;
       
    // Change object pointed to by ob.
        ob = new MyClass(11, 21);
       
    cout << *ob << endl;
       
    // Call a member function through a GCPtr.
        cout << "Sum is : " << ob->sum() << endl;
       
    // Assign a value to a class member through a GCPtr.  
        ob->val = 98.6;
        cout << "ob->val: " << ob->val << endl;
       
    cout << "ob is now " << *ob << endl;
      } catch(bad_alloc exc) {
       
    cout << "Allocation error!\n";
       
    return 1;
      }
     
    return 0;
    }

    Notice how the members of MyClass are accessed through the use of the –> operator. Remember, GCPtr defines a pointer type. Thus, operations through a GCPtr are performed in exactly the same fashion that they are with any other pointer.

    The output from the program, with the display option turned off, is shown here:

    (10 20)
    (11 21)
    Sum is : 32
    ob->val: 98.6
    ob is now (11 21)
    Destructing MyClass(11, 21)
    Destructing MyClass(10, 20)

    Pay special attention to the last two lines. These are output by ~MyClass( ) when garbage is collected. Even though only one GCPtr pointer was created, two MyClass objects were allocated. Both of these objects are represented by entries in the garbage collection list. When ob is destroyed, gclist is scanned for entries having a reference count of zero. In this case, two such entries are found, and the memory to which they point is deleted.

    More C++ Articles
    More By McGraw-Hill/Osborne


       · Your copy constructor and assignment operator are much too complicated and add lots...
       · I just worked on implementing your GC and testing it out in some of my code. I...
     

    Buy this book now. This article was excerpted from chapter two of The Art of C++, written by Herbert Schildt (McGraw-Hill/Osborne, 2004; ISBN: 0072255129). Check it out at your favorite bookstore today. Buy this book now.

    C++ ARTICLES

    - Large Numbers
    - Dijkstra`s Shunting Algorithm with STL and C...
    - Brief Introduction to the STL Containers
    - The Standard Template Library
    - Templates in C++
    - C++ Programmer Alerts
    - C++ Programming Tips
    - First Steps in (C) Programming, conclusion
    - First Steps in (C) Programming, continued
    - First Steps in (C) Programming, introduction
    - C++ Preprocessor: Always Assert Your Code Is...
    - C++ Preprocessor: The Code in the Middle
    - Programming in C
    - Temporary Variables: Runtime rvalue Detection
    - Temporary Variables: Chasing Temporaries Away







    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 5 hosted by Hostway