As I do keep tabs on what’s going on with C++ around the web, I chanced upon this short and succinct article about ?free’ and ?delete’ not returning memory to the OS from Thought Garage which starts with:
When you call free() or delete(), it will NOT really release any memory back to OS. Instead, that memory is kept with the same process until it is terminated. However, this memory can be reused for any future allocations by the same process.
It’s interesting to read this and remember some horror stories I saw with memory usage on long-running processes (HTTP servers to be exact). Is this true then?
I decided to check first by reading the documentation for libc’s free:
freecan actually return memory to the operating system and make the process smaller. Usually, all it can do is allow a later call to
mallocto reuse the space. In the meantime, the space remains in your program as part of a free-list used internally by
That’s not very clear although it mentions that occasionally memory will be returned to the OS. I dug a little deeper by looking at other malloc/free family of functions and saw ‘mallopt‘, and that you can actually change the way malloc/free behave (especially if you’re using GNU libc – pointers about other platform implementations would be helpful). One option that is interesting to look at is M_TRIM_THRESHOLD which:
This is the minimum size (in bytes) of the top-most, releasable chunk that will cause
sbrkto be called with a negative argument in order to return memory to the system.
So if you really want to control when you return memory to the operating system, then tuning malloc with mallopt would be a good option.
Another thing that came to mind when doing C++ development and when you know you will be making a lot of allocations of small objects from the heap is that object pools make a lot of sense. One popular implementation of an object pool is Boost.Pool – although there are some issues with using Boost.Pool’s standard allocator interface from my experience, using Boost.Pool’s object_pool and pool interface yield desirable results in situations where performance matters.
One way of getting around the Boost.Pool issues with the standard containers is by using Boost.Interprocess containers to use a stateful allocator instance that deals with a user-controlled Boost.Pool object_pool.
Do you have any tips with better memory management when developing C++ applications?