4

It took me many days and hours of efforts to narrow down on this. My application was consuming around 200 to 300 megabytes despite I was cleaning up everything. Finally I narrowed down that std::deque was the reason.

Code snippet below demonstrates this.

Platform: Windows 8

Compiler: Visual Studio 2012

Here am just pushing structures to deque and then poping them back and finally swapping it with blank deque to release memory fully (as suggested in answers of this or this)

#include <Psapi.h>

long long GetProcessPrivateBytes() 
{
    long long privatebytes;
    HANDLE current_process;
    PROCESS_MEMORY_COUNTERS_EX pmc;

    current_process = GetCurrentProcess();

    if (!GetProcessMemoryInfo(current_process, (PPROCESS_MEMORY_COUNTERS)&pmc, sizeof(pmc))) 
    {
        return -1;
    }

    privatebytes = pmc.PrivateUsage;

    return privatebytes ;
}

// Testing deque allocation
#define MYARRAY_SIZE 1024
#define MAX_ELEMENTS_IN_QUEUE (1024*1024)
struct MyStruct
{
    unsigned char MyArray[MYARRAY_SIZE];
};

int _tmain(int argc, _TCHAR* argv[])
{
    MyStruct mystruct;

    std::queue<MyStruct> MyStructQueue;

    while(1)
    {
        int MemoryConsumedByApplication = GetProcessPrivateBytes();

        std::cout << "\n\nCurrent memory consumed by application " << (MemoryConsumedByApplication/1024)/1024 << " Megabytes";

        if (MemoryConsumedByApplication > 128*1024*1014)
        {
            std::cout << "\nApplication still consuming too much memory. Press a key to quit the loop...";
            _getch();
            break;
        }

        std::cout << "\nFiling up queue with " << MAX_ELEMENTS_IN_QUEUE << " structs each of size " <<  MYARRAY_SIZE;
        for (int i=0; i<MAX_ELEMENTS_IN_QUEUE; i++)
        {
            MyStructQueue.push(mystruct);
        }

        std::cout << "\nQueue filled up. Now poping back all elements...";
        for (int i=0; i<MAX_ELEMENTS_IN_QUEUE; i++)
        {
            MyStructQueue.pop();
        }

        std::cout << "\nQueue poped back (Size " << MyStructQueue.size() << "). Now swaping with blank queue.";

        std::queue<MyStruct>().swap(MyStructQueue);
    }
    std::cout << "\nPress a key to exit...";
    _getch();
    return 0;
}

The output of this code is:

Current memory consumed by application 0 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 5 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 5 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 6 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 5 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 6 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 6 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 6 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 6 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 6 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 6 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 7 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 7 Megabytes
Filing up queue with 1048576 structs each of size 1024
Queue filled up. Now poping back all elements...
Queue poped back (Size 0). Now swaping with blank queue.

Current memory consumed by application 198 Megabytes
Application still consuming too much memory. Press a key to quit the loop...

Thus, it can be seen that after few iterations application holds bulk amount of memory and since there is nothing other than std::deque in the code, this memory must have been consumed by the std::deque.

Any idea why this happens and how to make application completely free of any allocation?

Community
  • 1
  • 1
Atul
  • 3,778
  • 5
  • 47
  • 87
  • It's certainly not the STL, read the tag wiki please, before using this tag or term. – πάντα ῥεῖ Oct 11 '15 at 08:26
  • 1
    Tag wiki gives general description of stl. This question is related to one of stl containers hence I added the tag. Other two questions (which I've referred in this question) on similar issue also have stl tagged in them. – Atul Oct 11 '15 at 08:33
  • 1
    Read it again, it's the old specific hp implementation. You are talking about the c++ standard library, we have 2015 now dude. – πάντα ῥεῖ Oct 11 '15 at 08:36
  • 1
    Omg, now I realized wht you were trying to suggest. I've made appropriate changes. I hope now it's in the order. – Atul Oct 11 '15 at 08:40
  • 1
    Does one additional iteration through the `while` loop make memory consumption jump suddenly from 7 MB to 198 MB as your output indicates? Or did you strip a lot of the output when you pasted it in your question? – WhiteViking Oct 11 '15 at 08:51
  • I can't reproduce this (linux gcc 5.1), are you sure your `GetProcessPrivateBytes()` isn't providing spurious results? – Galik Oct 11 '15 at 08:55
  • @WhiteViking: Nope I didn't stripped off any output line. It sudenly jumps from 7 MB to 198 MB in exact same iterations. – Atul Oct 11 '15 at 09:13
  • @Galik: It's in Windows 8. I verified through task manager it reports same amout of memory. – Atul Oct 11 '15 at 09:13
  • 1
    The answer to this question seems to lie in the exact meaning of `PROCESS_MEMORY_COUNTERS_EX.PrivateUsage` and deeper understanding of low-level Windows memory handling. Not in `std::deque` itself. – WhiteViking Oct 11 '15 at 09:22

0 Answers0