Introduction

C++ is the most popular language around. Although many people have shifted to other high level languages like VB and Java, it is still the language of choice for system programming and the situations where performance can never be compromised.

C++ offers great features for dynamic memory allocation and de-allocation, but you can hardly find any C++ programmer who hasn’t been bugged by memory leaks in C++ programs. The reason is that in C++, you have to de-allocate memory yourself which is, at times, bug provoking.

Some high level languages like Java and C# provide automatic memory de-allocation facility. These languages have a built in Garbage Collector which looks for any memory which has no further reference in the program and de-allocates that memory. So programmers don’t have to worry about memory leaks. How about having Garbage Collection facility in C++ programs?

Well, we can implement simple garbage collection facility in our programs using smart pointers, but it comes at some cost. There is a small overhead of an extra integer and a character variable per instance of classes for which you implement garbage collection. All source code for these garbage collection classes are provided with this article.

What are smart pointers?

I said we can implement garbage collection using “smart” pointers. But actually what are “smart” pointers?

C++ allows you to create “smart pointer” classes that encapsulate pointers, and override pointer operators to add new functionality to pointer operations. Template feature of C++ allows you to create generic wrappers to encapsulate pointers of almost any kind.

An example of smart pointers with templates could be a class which encapsulates double dimension arrays in C++.

This class encapsulates the functionality of double dimension arrays for any object in C++. You can extend the functionality of 2D arrays in this manner. Using the same technique, you can also implement STL style resizable collection classes like vector.

Now, coming back to garbage collection using smart pointers, how can we use smart pointers for garbage collection within the class?

What our Garbage Collector does?

We are embedding the garbage collection feature within a particular class. This simple garbage collector de-allocates memory when an object is no longer referenced, hence preventing memory leaks. This is really simple to implement.

We are using reference counting mechanism. Whenever there is a new reference to an object, we increment the reference count, and when it is no longer referenced, i.e. reference count=0, we de allocate the memory.

Implementation

The template class gcPtr<T> implements a garbage collecting pointer to any class derived from RefCount class.

This class implements simple reference counting. Any class which wishes to implement garbage collection should derive from this class. Note that RefCount takes a template parameter. This parameter is used to overload -> operator for the class which inherits from RefCount class to implement garbage collection. I.e.,

class foo : public RefCount<foo><FOO>
{
};

gcPtr is a template class using smart pointers which encapsulates all garbage collection processes.

Now, let’s see what happening in gcPt class template. There are two constructors. gcPtr() is for cases when you are just declaring the variable but not assigning memory to it using new operator. gcPtr(T*) is for cases when you are assigning memory to gcPtr variable on declaration using new operator. We have overloaded T* operator to provide support for array notation []. This returns us the T* type pointer which our class is encapsulating. -> operator is also overloaded to provide support for pointer operations like x->func(). This operator also returns the T* pointer. An interesting thing is happening in the case of assignments like x=y. gcPtr& operator=(gcPtr<T> &pIn) function is called, which in turn calls gcPtr& operator=(T* pIn) function, and only the ‘if’ block of this function is executed. Check this code:

We are type casting the input gcPtr parameter to T*. If x=y was the assignment (where x and y are variables of gcPtr<FOO>), this means we are type casting y to foo* and calling gcPtr& operator=((foo*) y) function. Now, let’s see how garbage collection mechanism is implemented in this function. Check this ‘if’ block code:

ptr->ReleaseRef();
// Decrement the reference count for ‘x’. Now if the
//reference count is zero, memory for x will
// be de-allocated
ptr = pIn; // assign (foo*) y to ptr which is
//of type foo
pIn->AddRef(); // Since we have made a new reference
//to (foo*) y, increment
//Reference count for (foo*)y
return *this; // return the x variable by reference.vv

So, this explains how garbage collection is done when an object is no longer referenced.

Now, to declare a pointer to your class, use gcPtr <T> class, passing the name of your class as template parameter. gcPtr<T> is a “smart” pointer. After allocating memory using new operator in one of the methods shown below, you can use gcPtr just like your class pointer. It supports all pointer operations. You don’t need to de-allocate memory using delete operator. It will be handled by gcPtr class.

=> Memory will be de-allocated when your object is no longer referenced. For example:

gcPtr<FOO> obj1=new obj;
// increment reference count for obj1 i.e refcount=1
gcPtr<FOO> obj2=new obj; // increment reference count for obj2
// i.e refcount=1
obj1=obj2; // decrement reference count for obj1
//i.e refcount=0 and increment
// reference count for obj2 i.e refcount=2 . Memory will
//be de-allocated
// for obj1. Now obj1 to the same memory as obj2
// When destructor for obj1 is called, it will decrement
//the referencecount to 1, and
//when destructor for obj2 is called, it will decrement it
// to 0 and memory is de-allocated.

That’s it. Isn’t it too simple to incorporate garbage collection and prevent memory leaks in C++? Of course; yes. What all you need is, to derive your class from Refcount.

How to implement garbage collection for built in data types?

To implement garbage collection for built-in data types like int, float etc., you can write a simple wrapper for them by overloading the operators.

class MyInt : public gcPtr<MYINT>
{
public:
int* val;
..... // overloaded operators like ++,--,> etc
..... // or overload these operators in
//RefCount base class
// so that they will be available to any class inheriting
// incorporating garbage collection
};

Instead of every time adding all operator overloads in your class, you can once modify RefCount class and provide overloaded operators for T data type, as one overloaded operator is already provided there: i.e., T* operator->(void) { return p; }.

Garbage collection in Action

Now, let's see Garbage Collection in action in a simple MFC Dialog Box application. Run your program in Debug mode and start debugging. If I am using garbage collection, here is the output from the output window:

I hope you enjoyed this article J. This is my first article on Code Project. Feel free to email me if you have any suggestions or if you have any problems using these classes + don’t forget to vote for me if you find this article useful .

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.