Detecting memory leak in reference counted objects

2019-04-29 02:23发布

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,

8条回答
闹够了就滚
2楼-- · 2019-04-29 03:03

Short answer: you should use the ideas that others posted, namely making use of ADD/RELEASE macros and passing the predefined __FILE__ and __LINE__ macros that the compiler provides to your tracking class.

Slightly longer answer: You can also use functionality that allows you to walk the stack and see who called the function, which is somewhat more flexible and clean than using macros, but almost certainly slower.

This page shows you how to achieve this when using GCC: http://tombarta.wordpress.com/2008/08/01/c-stack-traces-with-gcc/.

In Windows you can use some compiler intrinsics along with symbol-lookup functionality. For details check out: http://www.codeproject.com/tools/minidump.asp

Note that in both cases your program would need to include at least some symbols for this to work.

Unless you have special requirements for doing this at runtime, I'd suggest you check out the short answer.

查看更多
再贱就再见
3楼-- · 2019-04-29 03:04

One way to do what you asked, is to pass AddRef and Release this information using something like this:

void CReferenceCount::AddRef(const char *file=0, int line=-1) { if (file) cout << "FILE:" << file; if (line>0) count << " LINE: " << line;   .... do the rest here ... }

Then when you call the function, you can use a macro similar to what Rollie suggested above, like this:

#define ADDREF(x) x.AddRef(__FILE__, __LINE__)

This will pass the file and line where the call is made, which I believe is what you asked for. You can control what you want to do with the information within the methods. Printing them out, as I did above, is just an example. You may want to collect more information beyond this, and log it to another object, so you have a history of your calls, write them to a log file, etc. You may also pass more information from the call points than just the file and line, according to the type and level of tracking you need. The default parameters also allow you to use them without passing anything (by a simple macro redefinition), just to see how the final version will behave, with the overhead of two stack pushes and two condition checks.

查看更多
登录 后发表回答