简体   繁体   中英

C++ STL memory management in containers

I'm coding some mission critical code that I have to make sure it's absolutely free of memory leaks. I've wrote a small function that allows me to retrieve the memory usage at runtime and I make measurements before and after executing some code (that should be leak free) to see if memory usage remains on the same level.

While debugging a piece of code that was 'leaking', I finally found the culprit to be a vector container.

The minimal code that reproduces what I'm seeing is the following:

vector<char*>* v = new vector<char*>();
int n = 1024*1024;
while (n--)
{
     v->push_back(new char[256]()); // A
}
for (vector<char*>::iterator it=v->begin() ; it!=v->end() ; ++it )
{
     delete[] (*it);
}
delete v;

If you run that code (disabling compiler optimizations of course, -O0 ) and put some trap at the end so that the program doesn't exit (like cin.ignore(); ) you would see that your program should be using around 20Mb or so of memory.

I'd like to understand why does that happen. There's a line I marked with A , where if you allocate a larger char array you would see that the 'remaining' memory at the end is larger too. I wouldn't call this a leak per se beause apparently that memory could be reused if I allocate and fill another STL container, but still I would have expected to have that memory completely freed when the code finishes.

Can someone shed some light on to why is this memory still being used? And how may I 'free' it for real?

Some details about my compiler environment:

Using clang++: Apple LLVM version 6.0 (clang-600.0.51) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix

Compiling with: g++ -std=c++11 -g -Wall -Wextra -Wpedantic -O0 main.cc -o main.out

First, there is no excuse for dynamically allocating your container in your scenario. Why?

Second, it's a container of char* , and while it is responsible for managing those, you retain full and sole responsibility for whatever they point (or don't point) to!

Consider using vector<char> , unique_ptr<char> , string or something like that as the element-type to let the vector take that task.

Finally, keep in mind that the runtime-system uses its own allocator built on the OS primitives, so allocating memory does not directly translate to a request to the OS, nor does freeing / deleting it immediately return it there.
Doing so would be incredibly inefficient .

If you really want to make sure freed memory is returned to the OS, you have basically two options (which both involve writing your own allocator, or finding and using one someone else built):

  • Replace the replacable global allocation and deallocation functions with your own.
  • Use your own allocator for just those allocations (standard-containers are allocator-aware, which means you can provide your own allocator on a per-container basis).

After you are done, just ask your allocator to release everything back to the OS.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM