I'm working on a program using a large number of threads, each thread allocating in heap a few megabytes of memory. When these threads end, a large part of the RAM is kept by the program.
Here is an example of code, allocating and freeing 1 MB in 500 threads, which shows this problem:
#include <future>
#include <iostream>
#include <vector>
// filling a 1 MB array with 0
void task() {
const size_t S = 1000000;
int * tab = new int[S];
std::fill(tab, tab + S, 0);
delete[] tab;
}
int main() {
std::vector<std::future<void>> threads;
const size_t N = 500;
std::this_thread::sleep_for(std::chrono::seconds(5));
std::cout << "Starting threads" << std::endl;
for (size_t i = 0 ; i < N ; ++i) {
threads.push_back(std::async(std::launch::async, [=]() { return task(); }));
}
for (size_t i = 0 ; i < N ; ++i) {
threads[i].get();
}
std::cout << "Threads ended" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(25));
return 0;
}
On my computer, this code, simply built with g++ -o exe main.cpp -lpthread
, uses 1976 kB before the message "Starting threads", and 419 MB after the message "Threads ended". These values are just examples: when I run the program multiple times, I can get different values.
I have tried valgrind / memcheck, but it doesn't detect any leak.
I have noticed that locking the "std::fill" operation with a mutex seems to solve this issue (or largely reduce it), but I don't think this is a race condition problem, as there is no shared memory here. I guess the mutex simply creates an execution order between the threads which avoid (or reduce) the conditions in which the memory leaks.
I am using Ubuntu 18.04, with GCC 7.4.0.
Thank you for your help.
Aurélien