The code below provokes a strange memory behavior on my Debian machine. Even after maps are cleared, htop shows that the program still uses a lot of memory, which makes me think there is a memory leak. The strange fact is that it only appears under some circumstances.
#include <map>
#include <iostream>
#include <memory>
int main(int argc, char** argv)
{
if (argc != 2)
{
std::cout << "Usage: " << argv[0] << " <1|0> " << std::endl;
std::cout << "1 to insert in the second map and see the problem "
"and 0 to not insert" << std::endl;
return 0;
}
bool insertion = atoi(argv[1]);
std::map<uint64_t, std::shared_ptr<std::string> > mapStd;
std::map<uint64_t, size_t> counterToSize;
size_t dataSize = 1024*1024;
uint64_t counter = 0;
while(counter < 10000)
{
std::shared_ptr<std::string> stringPtr =
std::make_shared<std::string>(dataSize, 'a');
mapStd[counter] = stringPtr;
if (insertion)
{
counterToSize[counter] = dataSize;
}
if (counter > 500)
{
mapStd.erase(mapStd.begin());
}
std::cout << "\rInserted chunk " << counter << std::flush;
counter++;
}
std::cout << std::endl << "Press ENTER to delete the maps" << std::endl;
char a;
std::cin.get(a); // wait for ENTER to be pressed
mapStd.clear(); // clear both maps
counterToSize.clear();
std::cout << "Press ENTER to exit the program" << std::endl;
std::cin.get(a); // wait for ENTER to be pressed
return 0;
}
Explanation:
The code creates two maps on the stack (but issue is the same if they are created on the heap). It then inserts std::shared_ptr of strings to the first map. Each string has a size of 1MB. Once 500 strings are inserted, one deletes the first one for each new insert, so that the total memory used by the map is always equal to 500MB. When a total of 10000 strings have been inserted, the program waits for the user to press ENTER. If you launch the program and pass 1 as first argument, then, for each insertion in the first map, another insertion is also made to the second map. If the first argument is 0, then the second map is not used. Once ENTER is pressed for the first time, both maps are cleared. The program still runs and waits again for ENTER to be pressed, and then exits.
Here are the facts:
On my 64-bit Debian 3.2.54-2, after ENTER is pressed (thus after the maps are cleared), and when the program is launched with 1 as first argument (thus with insertion in the second map), htop indicates that the program STILL USE 500MB OF MEMORY!! If the program is launched with 0 as first argument, then the memory is correctly released.
This machine uses g++4.7.2 and libstdc++.so.6.0.17. I've tried with g++4.8.2 and libstdc++.so.6.0.18, same issue.
- I've tried on a 64bit Fedora 21 with g++4.9.2 and libstdc++.so.6.0.20, same issue.
- I've tried on an 32 bit Ubuntu 14.04 with g++4.8.2 and libstdc++.so.6.0.19, the problem does NOT appear!
- I've tried on an 32 bit Debian 3.2.54-2 with g++4.7.2 and libstdc++.so.6.0.17, the problem does NOT appear!
- I've tried on 64-bit Windows, the problem does NOT appear!
- On a machine where the problem exists, if you invert the lines where the maps are cleared (thus if you clear first the uint64_t, size_t map, the problem disappear!
Does somebody have an explanation for all this ???