C++
  Home arrow C++ arrow Page 11 - 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  
Mobile Linux 
App Generation ROI 
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 / 44
    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
     
     
    ADVERTISEMENT


    A Simple Garbage Collector for C++ - A Larger Demonstration Program


    (Page 11 of 12 )

    The following program shows a larger example that exercises all of the features of GCPtr:

    // Demonstrating GCPtr.
    #include <iostream>
    #include <new>
    #include "gc.h"
    using namespace std;
    // A simple class for testing GCPtr with class types.
    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);
    };
    // Create an inserter for MyClass.
    ostream &operator<<(ostream &strm, MyClass &obj) {
      strm << "(" << obj.a << " " << obj.b << ")";
      return strm;
    }
    // Pass a normal pointer to a function.
    void passPtr(int *p) {
      cout << "Inside passPtr(): "
           << *p << endl;
    }
    // Pass a GCPtr to a function.
    void passGCPtr(GCPtr<int, 0> p) {
      cout << "Inside passGCPtr(): "
           << *p << endl;
    }
    int main() {
     
    try {
        // Declare an int GCPtr.
        GCPtr<int> ip;
       
    // Allocate an int and assign its address to ip.
        ip = new int(22);
       
    // Display its value.
        cout << "Value at *ip: " << *ip << "\n\n";
       
    // Pass ip to a function
        passGCPtr(ip);
       
    // ip2 is created and then goes out of scope 
        {
         GCPtr<int> ip2 = ip;
        }
       
    int *p = ip; // convert to int * pointer'
       
    passPtr(p); // pass int * to passPtr()
       
    *ip = 100; // Assign new value to ip
       
    // Now, use implicit conversion to int *
        passPtr(ip);
        cout << endl;
       
    // Create a GCPtr to an array of ints
        GCPtr<int, 5> iap = new int[5];
       
    // Initialize dynamic array.
        for(int i=0; i < 5; i++)
          iap[i] = i;
       
    // Display contents of array.
        cout << "Contents of iap via array indexing.\n";
        for(int i=0; i < 5; i++)
         
    cout << iap[i] << " ";
        cout << "\n\n";
       
    // Create an int GCiterator.
        GCPtr<int>::GCiterator itr;
       
    // Now, use iterator to access dynamic array.
        cout << "Contents of iap via iterator.\n";
        for(itr = iap.begin(); itr != iap.end(); itr++)
         
    cout << *itr << " ";
        cout << "\n\n";
       
    // Generate and discard many objects
        for(int i=0; i < 10; i++)
          ip = new int(i+10);
       
    // Now, manually garbage collect GCPtr<int> list.
        // Keep in mind that GCPtr<int, 5> pointers
        // will not be collected by this call.
        cout << "Requesting collection on GCPtr<int> list.\n";
        GCPtr<int>::collect();
       
    // Now, use GCPtr with class type.
        GCPtr<MyClass> ob = new MyClass(10, 20);
       
    // Show value via overloaded insertor.
        cout << "ob points to " << *ob << endl;
       
    // Change object pointed to by ob.
        ob = new MyClass(11, 21);
        cout << "ob now points to " << *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 = 19.21;
        cout << "ob->val: " << ob->val << "\n\n";
       
    cout << "Now work with pointers to class objects.\n";
       
    // Declare a GCPtr to a 5-element array
        // of MyClass objects.
        GCPtr<MyClass, 5> v;
        // Allocate the array.
        v = new MyClass[5];
       
    // Get a MyClass GCiterator.
        GCPtr<MyClass>::GCiterator mcItr;
       
    // Initialize the MyClass array.
        for(int i=0; i<5; i++) {
          v[i] = MyClass(i, 2*i);
        }
       
    // Display contents of MyClass array using indexing.
        cout << "Cycle through array via array indexing.\n"; 
        for(int i=0; i<5; i++) {
         
    cout << v[i] << " ";
        }
        cout << "\n\n";
       
    // Display contents of MyClass array using iterator. 
        cout << "Cycle through array through an iterator.\n"; 
        for(mcItr = v.begin(); mcItr != v.end(); mcItr++) {
         
    cout << *mcItr << " ";
        }
        cout << "\n\n";
       
    // Here is another way to write the preceding loop. 
        cout << "Cycle through array using a while loop.\n"; 
        mcItr = v.begin();
        while(mcItr != v.end()) {
         
    cout << *mcItr << " ";
         
    mcItr++;
        }
        cout << "\n\n";
       
    cout << "mcItr points to an array that is "
             << mcItr.size() << " objects long.\n";
       
    // Find number of elements between two iterators. 
        GCPtr<MyClass>::GCiterator mcItr2 = v.end()-2;
        mcItr = v.begin();
        cout << "The difference between mcItr2 and mcItr is "
            
    << mcItr2 - mcItr;
        cout << "\n\n";
       
    // Can also cycle through loop like this.
        cout << "Dynamically compute length of array.\n";
        mcItr = v.begin();
        mcItr2 = v.end();
        for(int i=0; i < mcItr2 - mcItr; i++) {
         
    cout << v[i] << " ";
        }
       
    cout << "\n\n";
       
    // Now, display the array backwards.
        cout << "Cycle through array backwards.\n";
        for(mcItr = v.end()-1; mcItr >= v.begin(); mcItr--)
         
    cout << *mcItr << " ";
        cout << "\n\n";
       
    // Of course, can use "normal" pointer to
        // cycle through array.
        cout << "Cycle through array using 'normal' pointer\n";
        MyClass *ptr = v;
        for(int i=0; i < 5; i++)
         
    cout << *ptr++ << " ";
        cout << "\n\n";
       
    // Can access members through a GCiterator.
        cout << "Access class members through an iterator.\n";
        for(mcItr = v.begin(); mcItr != v.end(); mcItr++) {
         
    cout << mcItr->sum() << " ";
        }
        cout << "\n\n";
       
    // Can allocate and delete a pointer to a GCPtr
        // normally, just like any other pointer.
        cout << "Use a pointer to a GCPtr.\n";
        GCPtr<int> *pp = new GCPtr<int>();
        *pp = new int(100);
        cout << "Value at **pp is: " << **pp;
        cout << "\n\n";
       
    // Because pp is not a garbage collected pointer,
        // it must be deleted manually.
        delete pp;
     
    } catch(bad_alloc exc) {
        // A real application could attempt to free
        // memory by collect() when an allocation
        // error occurs.
        cout << "Allocation error.\n";
     
    }
     
    return 0;
    }

    Here is the output with the display option turned off:

    Value at *ip: 22
    Inside passGCPtr(): 22
    Inside passPtr(): 22
    Inside passPtr(): 100
    Contents of iap via array indexing.
    0 1 2 3 4
    Contents of iap via iterator.
    0 1 2 3 4
    Requesting collection on GCPtr<int> list.
    ob points to (10 20)
    ob now points to (11 21)
    Sum is : 32
    ob->val: 19.21
    Now work with pointers to class objects.
    Destructing MyClass(0, 0)
    Destructing MyClass(1, 2)
    Destructing MyClass(2, 4)
    Destructing MyClass(3, 6)
    Destructing MyClass(4, 8)
    Cycle through array via array indexing.
    (0 0) (1 2) (2 4) (3 6) (4 8)
    Cycle through array through an iterator.
    (0 0) (1 2) (2 4) (3 6) (4 8)
    Cycle through array using a while loop.
    (0 0) (1 2) (2 4) (3 6) (4 8)
    mcItr points to an array that is 5 objects long.
    The difference between mcItr2 and mcItr is 3
    Dynamically compute length of array.
    (0 0) (1 2) (2 4) (3 6) (4 8)
    Cycle through array backwards.
    (4 8) (3 6) (2 4) (1 2) (0 0)
    Cycle through array using 'normal' pointer
    (0 0) (1 2) (2 4) (3 6) (4 8)
    Access class members through an iterator.
    0 3 6 9 12
    Use a pointer to a GCPtr.
    Value at **pp is: 100
    Destructing MyClass(4, 8)
    Destructing MyClass(3, 6)
    Destructing MyClass(2, 4)
    Destructing MyClass(1, 2)
    Destructing MyClass(0, 0)
    Destructing MyClass(11, 21)
    Destructing MyClass(10, 20)

    On your own, try compiling and running this program with the display option turned on. (That is, define DISPLAY in gc.h.) Next, walk through the program, matching the output against each statement. This will give you a good feel for the way the garbage collector works. Remember, garbage collection occurs whenever a GCPtr goes out of scope. This happens at various points in the program, such as when a function that receives a copy of a GCPtr returns. In this case, the copy goes out of scope and garbage collection takes place. Also remember that each type of GCPtr maintains its own gclist. Thus, collecting garbage from one list does not cause it to be collected from other types of lists.

    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...
       · one comment is clearly missing here: this is a great article.
       · Sir,The article is very informative.Thanks a lot.But there are instances when...
     

    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

    - Paths and Files
    - Directories in C++
    - Focusing on C++ Files
    - Const Correctness in C++
    - Manipulating Streams and Files with C++
    - Streams and Files
    - Multiplying Large Numbers with Karatsuba`s A...
    - 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






    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 3 hosted by Hostway
    Stay green...Green IT