My experiences with reference counting

Featured

For two years I used reference counting as a way to find object leaks in my code, special in my private projects.
I wanted to be able to find a missing release call much faster and I looked for a simple method to find the number
of not released objects in my code.

So I wrote a small base-class called IObject, which supports a simple internal reference count like:

class IObject
{
public:
    IObject( const std::string &name );
    void get();
    void release();

private:
    IObject();
    IObject &operator = ( const IObject &r );
    virtual ~IObject();
    std::string m_Name;
    unsigned int m_NumRefs;
};

A user can generate an object instance on the heap. if you want to share this the second instance which is working with this instance has to call get. This will increase the reference count by 1. After finishing the work the user must call release, which will decrease the reference count by one. If the number of references is zero the release-method will delete the instance itself.
The constructor will init the reference count with one. If you have finished your work you can release the instance. Explicite calls of the destructor are forbitten.
You see its pretty simple. The base object has an attribute to store its name. You can use this to see, which objects still have not release references in their code.
It sounds pretty easy at the first look, but after a while I saw more and more leaked references I wasn’t able to locate. So I intorduced a simple smart-pointer, which responsibility is managing the release automatically by using RAII. But the issue was not solved with this approach.
After a while I learned what went wrong:

  • Circular dependencies: the parent node owns a child node. The child node owns a reference to the parent as well. Not good! The solution was pretty simple: the child just owns a leak reference to the parent without incrementing the reference count.
  • When an object cache creates a new instance and stores a pointer showing to it I increment the number of reference, too. So the object itself at the beginning of its life has a reference count of one. The Cache increments it, too. When the cache will be destroyed the reference will be dropped and the reference count is decremented by one. But there is one reference left as well. After I have understand this the solution was pretty simple: avoid the unnessesary get-call.
  • I haven’t fixed all my leaks yet but I was suprised how many errors I made with such a simple approach and how much time it take to understand and fix them.