2

I found a strange thing, memory seems not freed in C++ after class destructs.

The following code can be used to reproduce the problem.

#include <iostream>
#include <map>
#include <vector>
#include "sys/sysinfo.h"
#include "sys/types.h"

class MemoryConsumer
{
public:
    explicit MemoryConsumer(int size_1, int size_2)
        : consumer(size_1)
    {
        std::cout << "call constructor" << std::endl;
        // no meaning, just consume memory
        for (int i = 0; i < size_1; i++)
        {
            for (int j = 0; j < size_2; j++)
            {
                double value = (i + j) * (i - j);
                consumer[i].insert(std::pair<int, double>(j, value));
            }
        }
    }
    ~MemoryConsumer ()
    {
        std::cout << "call destructor" << std::endl;
    }
    private :
    // no meaning, just consume memory
    std::vector<std::map<int, double>> consumer;
};

void showMemory()
{
    // Reference:
    // https://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process
    struct sysinfo memInfo;

    sysinfo(&memInfo);

    long long physical_memory_used = memInfo.totalram - memInfo.freeram;
    // Multiply in next statement to avoid int overflow on right hand side...
    physical_memory_used *= memInfo.mem_unit;

    double physical_memory_used_in_GB = physical_memory_used * 1.0 / 1024 / 1024 / 1024;

    std::cout << "total physical memory used: " << physical_memory_used_in_GB << " GB." << std::endl;
}

void doOtherCalculation()
{
    double x = 0;
    for (int i = 0; i < 1e8;i++)
    {
        x = x + 1;
    }
    std::cout << " x = " << x << std::endl;
}

int main()
{
    showMemory();
    MemoryConsumer *consumer = new MemoryConsumer(600000, 100);
    showMemory();
    delete consumer;
    showMemory();
    doOtherCalculation();
    showMemory();
    return 0;
}

I run the code using g++ main.cpp -O3, the platform is Ubuntu 18.04, and the result on my computer is

total physical memory used: 16.5366 GB.
call constructor
total physical memory used: 20.1367 GB.
call destructor
total physical memory used: 20.1182 GB.
 x = 1e+08
total physical memory used: 20.1217 GB.

A similar result can be observed using -O0 options.

It can be observed from the result that, After creating a memory consumer, 3.6 GB is being consumed. After deleting the consumer, the 3.6 GB memory not be freed. Even after doing some calculations, the 3.6GB still not be freed.

My problem is:

problem 1

I think the std::vector and std::map can manage the memory itself. So why this stage can happen? The memory seems not to be freed after call destructor. I think all memory should be freed, then the process can go ahead to do other calculation.

problem 2

How can I wait until all 3.6GB freed, then I start to do other calculations? Is there exist some thing like a "barrier"?

I apologize if it is a silly problem. Thanks for your time.

Xu Hui
  • 1,213
  • 1
  • 11
  • 24
  • 4
    The vector is properly destructed and the memory is freed. It's simply that linux does not immediately counts that memory as freed. If another application needs that memory, then rest assured it will be made available by the kernel. See e.g. https://stackoverflow.com/questions/21433976/free-not-freeing-memory-in-embedded-linux. – AVH Oct 29 '20 at 11:02
  • What happens if you set ~MemoryConsumer=default ? – Henry Le Berre Oct 29 '20 at 11:02
  • @PolarToCartesian Sir, the memory result is 27 31,31,31, the memory still seems not to be freed. – Xu Hui Oct 29 '20 at 11:04
  • 2
    When a C++ program frees memory, it does not return it to the OS. Rather the program tracks the memory as free and will reuse that heap memory, until/unless it needs more than available in the heap — at which time it will ask the OS for another block of memory. (Some platforms may have a mechanism for the OS to ask for the memory back, but more likely the OS will just swap out the memory to file.) – Eljay Oct 29 '20 at 11:31

0 Answers0