I have a class which has a field of type unordered_map
. I create a single instance of this object in my application, which is wrapped in a shared_ptr
. The object is very memory consuming and I want to delete it as soon as I'm done using it. However, resetting the pointer only frees a small part of the memory occupied by the object. How can I force the program to free all the memory occupied by the object?
The following mock program reproduces my problem. The for loops printing garbage are there only to give me enough time to observe the memory used with top
. The destructor gets called just after reset()
. Also, immediately after, the memory used drops from approx 2 GB to 1.5 GB.
#include <iostream>
#include <memory>
#include <unordered_map>
using namespace std;
struct A {
~A() {
cerr << "Destructor" << endl;
}
unordered_map<int, int> index;
};
int main() {
shared_ptr<A> a = make_shared<A>();
for (size_t i = 0; i < 50000000; ++i) {
a->index[2*i] = i + 3;
}
// Do some random work.
for (size_t i = 0; i < 3000000; ++i) {
cout << "First" << endl;
}
a.reset();
// More random work.
for (size_t i = 0; i < 3000000; ++i) {
cout << "Second" << endl;
}
}
Compiler: g++ 4.6.3.
GCC's standard library has no "STL memory cache", in its default configuration (which almost everyone uses) std::allocator
just calls new
and delete
, which just call malloc
and free
. The malloc
implementation (which usually comes from the system's C library) decides whether to return memory to the OS. Unless you are on an embedded/constrained system with no virtual memory (or you've turned off over-committing) then you probably do not want to return it -- let the library do what it wants.
The OS doesn't need the memory back, it can allocate gigabytes of virtual memory for other applications without problems. Whenever people think they need to return memory it's usually because they don't understand how a modern OS handles virtual memory.
If you really want to force the C library to return memory to the OS, the C library might provide non-standard hooks to do so, e.g for GNU libc you can call malloc_trim(0)
to force the top-most chunk of free memory to be returned to the OS, but that will probably make your program slower next time it needs to allocate more memory, because it will have to get it back from the OS. See https://stackoverflow.com/a/10945602/981959 (and the other answers there) for more details.
There's no guarantee that your application will free the memory back to the OS. It's still available for your application to use but the OS may not reclaim it for general use until your application exits.