hANI
hANI

Reputation: 213

How to check for memory leaks in a class in C++?

I am aware of several other threads that have discussed a similar questions. Also I am aware that one must deallocate all the allocated resources and nothing should be left unaccounted for. The reason I am asking this question is to see if there is a way to automatically detect a memory leak in a class. In particular, I am trying to implement an automated way to detect the leak within the unittest so that future development of that class would be more robust. Since my class is using several other classes within and some DLL's as well, it is difficulat, if not impossible to keep track of the leaks in all of those, so such a unittest may help.

I was thinking of a couple of solutions to be able to check for memory leaks within a class. Assuming my class is something similar to this:

class MyClass
{
    MyClass() { /* Lots of allocations */ }
    ~MyClass() { /* Lots of deallocations */ }
}
  1. In the test function, instantiate the class instance many times and destruct everytime. Meanwhile, check the task manager (in Windows at least) to see if the allocated memory for your application ramps up or remains substantially flat:

    TEST( MyClass, MyClass)
    {
        int some_big_number = 10000;
        for (int i=0; i<some_big_number; i++)
        {
            MyClass *myC = new MyClass;
            delete myC;
        }
    }
    
  2. Allocate some dummy variable before and after the instantiation and destruction of the class instance and check if the two addresses are the same. Something like this:

    TEST( MyClass, MyClass)
    {
        int address_1 = 0, address_2 = 0;
    
        int *tmp_1 = new int;
        address_1 = tmp_1;
        delete tmp_1;
    
        MyClass *myC = new MyClass;
        delete myC;
    
        int *tmp_2 = new int;
        address_2 = tmp_2;
        delete tmp_2;
    
        EXPECT_TRUE( address_1 == address_2 );
    }
    

    My assumption is that if there is no memory leak within MyClass and all the claimed memory has been properly deallocated, the addresses of tmp_1 and tmp_2 should be the same. I am just not sure if memory allocation works that way.

  3. Use a plugin or program such as deleaker or Valgrind, but that may make my code or test unfavorably large and I am not sure if that can be used in the context above anyway.

Thanks!

Upvotes: 3

Views: 1362

Answers (4)

Jeff Loughlin
Jeff Loughlin

Reputation: 4174

Your second idea won't work because you won't get the same address each time.

However your first idea is a good start, and I will try to improve upon that here. Instead of watching the task manager, you can automate that part of it by calling GetProcessMemoryInfo(). See this answer for information on how to do that. The value you want to look at in the returned data structure is PrivateUsage. If you do that before instantiating your class object and again after deleting it, your memory usage should be the same. Also, if any other methods on your class do any memory allocation, you'll want to call them in there too. This way your test case can give your class a good workout without any human intervention, and you can make it do whatever you want (log something, raise an alert, whatever) if it detects that memory usage is rising.

Something like this:

// Get the starting memory usage
int baseline = GetMemoryUsage();   // This is the function that calls GetProcessMemoryInfo() as described in the link above

MyClass *myC = new MyClass;
int memUsage = GetMemoryUsage();
myC->DoStuff();
if (GetMemoryUsage() != memUsage)
    Alert("Detected memory leak in MyClass::DoStuff()");
memUsage = GetMemoryUsage();
myC->DoMoreStuff();
if (GetMemoryUsage() != memUsage)
    Alert("Detected memory leak in MyClass::DoMoreStuff()");
// ...
// etc - call each method that does any kind of memory allocation
// ...
delete myC;
if (GetMemoryUsage() != baseline)
    Alert("Detected memory leak in MyClass");


To implement the GetMemoryUsage() function referenced above, you can do something like this (I don't have a compiler in front of me right now, so forgive any typos):

#include <windows.h>
#include <psapi.h>
#pragma comment(lib, "psapi.lib") 

int GetMemoryUsage();
{
    PROCESS_MEMORY_COUNTERS_EX pmc;

    DWORD processId = GetCurrentProcessId();
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
                                    PROCESS_VM_READ,
                                    FALSE, processID);
    if (hProcess == NULL)
        return -1;

    if (GetProcessMemoryInfo( hProcess, (PROCESS_MEMORY_COUNTERS *) &pmc, sizeof(pmc)))
    {
        CloseHandle(hProcess);
        return pmc.PrivateUsage;
    }

    CloseHandle(hProcess);
    return -1;
}

Upvotes: 1

Mau
Mau

Reputation: 14478

If you're using VC++, VLD is nice and small and works wonders.

Upvotes: 2

Claudiordgz
Claudiordgz

Reputation: 3049

@galop1n is correct, regardless this is how you handle leaks in general.

But you did touch a valid point, which is DLL Memory Management. You see an object from a DLL needs to handle memory differently. You delegate to a certain point that memory management to your library. Inside your library the memory will be allocated in the order they defined. And they will provide with methods to free this memory (for example cudaFree from the CUDA Libraries).

You should handle your memory in the object's constructor and destructor. The C++ standard provides some great mechanisms to handle memory for you. unique_ptr and shared_ptr are a great example of this in C++11, you can also use containers from the std for the same end.

Valgrind is also a great tool once you already did everything already mentioned. Once you used every possible tool provided by C++ then it's time to double check your memory usage with this awesome tool

Upvotes: 3

Scholar
Scholar

Reputation: 293

Seems like what you are looking for is the utility valgrindit gives critical information regarding to how memory is managed and released in your program.

Check it out at valgrind.org

Upvotes: 0

Related Questions