3

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!

hANI
  • 213
  • 3
  • 13
  • 3
    There is no guaranty at all that tmp_2 will got the same address. This is implementation dependent details of the underlying allocator. – galop1n Mar 24 '14 at 16:07
  • 4
    What about http://valgrind.org/ – bosnjak Mar 24 '14 at 16:07
  • 2
    `Also I am aware that one must deallocate all the allocated resources and nothing should be left unaccounted for` How about using constructs that do this work automatically, such as containers and smart pointers? – PaulMcKenzie Mar 24 '14 at 16:17
  • What about using a comparison of memory use before and after creating the class under test instance(s) and then again after calling the class under test destructor(s)? A quick Internet search has found this site for multiple platform methods to find memory in use: [C/C++ tip: How to get the process resident set size - physical memory use](http://nadeausoftware.com/articles/2012/07/c_c_tip_how_get_process_resident_set_size_physical_memory_use). – CPlusPlus OOA and D Mar 24 '14 at 16:19
  • You should have told us what IDE you use. Try http://vld.codeplex.com/ for Microsoft Visual studio projects. Microsofts built in leak detector sucks. – shawn1874 Mar 24 '14 at 17:05
  • I am using VC++ 2008. I have seen the vld plugin, but I don't think it can be used as part of an automated test or used as a solution for all team members working on the same project. – hANI Mar 24 '14 at 17:36

4 Answers4

3

@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

Claudiordgz
  • 3,023
  • 1
  • 21
  • 48
2

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

Mau
  • 14,234
  • 2
  • 31
  • 52
1

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;
}
Community
  • 1
  • 1
Jeff Loughlin
  • 4,134
  • 2
  • 30
  • 47
  • I will give this a try and will let you know if it works for me. Where can I find GetMemoryUsage()? It is not in Psapi.h with the syntax you used. Other functions like GetProcessMemoryInfo() need a process handle which I don't have as I don't know about all the threads that are running within MyClass. – hANI Mar 24 '14 at 17:30
  • You need to implement GetMemoryUsage() based on the link I gave you in the answer. You'll get a process handle from OpenProcess(), as shown in the code sample there. Threads don't matter here - you're getting process info – Jeff Loughlin Mar 24 '14 at 17:37
  • I've edited the answer to provide you with a sample implementation of GetMemoryUsage() – Jeff Loughlin Mar 24 '14 at 19:08
  • To make use of the functions above I had to add the following in the heading: #include #include #pragma comment( lib, "psapi.lib" ) – hANI Mar 25 '14 at 05:39
  • Glad it helped - I edited the code above to add the #includes so it will be easier for the next person who comes across this post – Jeff Loughlin Mar 25 '14 at 12:06
0

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

Scholar
  • 293
  • 3
  • 8
  • 16