Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting memory leak in reference counted objects

I am trying to print on which line addref and release is called.Here is code

In code below I have created on ReferenceCount class whose main functionality to increase and decrease refernce count. Referencemanager class keeps track of reference count and deletes the object once it reaches 0.

Test1 is test class .In main I am creating Test1 pointer and wrapping it with CReferenceManager class. Now during creation of CReferenceManager class AddRef is called and while destruction Release would be called.

If there is memory leak then it would be easier to detect if I can print out FILE and LINE numbers when AddRef and Release called with reference counts at that point.

If there a way that I can print FILE and LINE number from where AddRef and Release gets called. One way is that I can overwrite AddRef and Release in derived classes and prinf FILE and LINE numbers

//ReferenceCount.h
#include <string>
#include <Windows.h>

using namespace std;
class CReferenceCount
{
public:
   CReferenceCount();
   virtual ~CReferenceCount();
   virtual void AddRef();
   virtual bool Release();


private:
   LONG m_ref;

};


// RefCount.cpp 
//

#include "stdafx.h"
#include "ReferenceCount.h"


CReferenceCount::CReferenceCount():m_ref(0)
{
   AddRef();

}

CReferenceCount::~CReferenceCount()
{
}

void CReferenceCount::AddRef()
{
    InterlockedIncrement(&m_ref);
}

bool CReferenceCount::Release()
{
   if (InterlockedDecrement(&m_ref) == 0)
   {
      delete this;
      return true;
   }

   return false;
}



//ReferenceManager.h
#include <string>
#include <Windows.h>

using namespace std;
class CReferenceCount
{
public:
   CReferenceCount();
   virtual ~CReferenceCount();
   virtual void AddRef();
   virtual bool Release();


private:
   LONG m_ref;

};

//test.cpp
#include "stdafx.h"
#include "ReferenceCount.h"
#include "RefManager.h"
#include <iostream>
using namespace std;

class Test1: public CReferenceCount
{
public:
    Test1(){}
    ~Test1(){}

private :
    int m_i;
};

void main()
{
    Test1 *pTest= new Test1();
    CReferenceManager<Test1> testRef(pTest);

}

Similare questions I have posted finding who creates object via smart pointer Design pattern to detect memory leaks for reference counted smart pointers

but non of the answers give right explanation to tackle this proble,

like image 201
anand Avatar asked Oct 10 '12 19:10

anand


1 Answers

The only way is to define macros for calling AddRef and Release, since there is no way for the functions to know internally from where they are being called. So you could use something like.

#define RELEASE(obj) cout << __LINE__ << ":" << __FILE__ << endl; (obj).Release();

Also, different compilers have different pre-defined macros; if portability is a concern, it's something you should look into when writing code like the above. MSDN reference (2003)

Given your comments below, i might offer another somewhat hackish solution. You may not be able to see where your reference is being released, but you can get more information about where it was created, and which are not being released properly.

template <typename T>
struct CReferenceManager
{
    CReferenceManager(const T & _obj, const string & _file, int _line) : mObj(_obj), mFile(_file), mLine(_line)
    {
        cout << "Constructing from " << _file << ":" << _line << endl;
        CReferenceManager::sObjects[make_pair(mFile, mLine)]++;
        mObj.addRef();
    }

    ~CReferenceManager()
    {
        cout << "Destructing object created at " << mFile << ":" << mLine << endl;
        CReferenceManager::sObjects[make_pair(mFile, mLine)]--;
        mObj.Release();
    }

    static map<pair<string, int>, int> sObjects;
    string mFile;
    int mLine;
    T obj;
}

int main()
{
...
    // Cycle through sObjects before return, note any unreleased entries
    return 0;
}

Note this is just pseudo-code; I doubt it compiles or works out of the box!

like image 115
Rollie Avatar answered Sep 21 '22 01:09

Rollie