user3572917
user3572917

Reputation: 45

C++ - are these threads destroyed after the for loop is completed

for (int i = 0; i < 10; i++) {
    thread *t = new thread(example_function);
    t->join();
}

I am doing something similar in a coding project of mine and was wondering if since the threads get defined inside the loop they are destroyed after the loop ends (I know the pointer to the thread probably gets deleted but what about the thread itself?).

Upvotes: 1

Views: 952

Answers (4)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726569

No, thread objects created inside the for loop are not destroyed, which means that they create memory leaks.

In order to make sure that the threads are destroyed you need to call delete on them in one of several ways:

  • Call delete at the end of the scope, or
  • Add thread pointers to a container of pointers, and call delete in a separate loop, or
  • Add thread pointer to a smart pointer that ensures deletion when the scope ends, or
  • Add thread pointers to a container of smart pointers, and let the container delete the threads when it goes out of scope.

Note that since you are calling join on each loop iteration your "concurrent" program is as good as a single-threaded one. Here is how to run your threads concurrently, and ensure thread deletions at the end:

std::vector<std::unique_ptr<std::thread>>> threads;
for (int i = 0; i < 10; i++) {
    threads.push_back(std::make_unique<thread>(example_function));
}
for (int i = 0; i < 10; i++) {
    threads[i]->join();
}

Once threads vector goes out of scope, it deletes std::unique_ptr<thread> objects inside it, which in turn calls delete on the individual std::thread objects.

Upvotes: 4

Slava
Slava

Reputation: 44248

I am doing something similar in a coding project of mine and was wondering if since the threads get defined inside the loop they are destroyed after the loop ends

Whole purpose of dynamic allocation using operator new is to provide manual control over object lifetime. So no, until you explicitly call delete or you use a smart pointer that does it for you under the hood your object would not be destroyed. Note, calling std::thread::join() inside the loop effectively would make your program single threaded. More proper use would be:

std::vector<std::thread> threads;
while( threads.size() < 10 )
    threads.emplace_back(example_function);

for( auto &thread : threads )
    thread.join(); // join in a separate loop, let all threads to start

threads.clear(); // or let it go out of scope

Upvotes: 2

Persixty
Persixty

Reputation: 8589

No. The caller is responsible for ensuring objects allocated using new are deleted.

The code is of course pretty pointless because no meaningful concurrency occurs but to avoid a memory leak should be:

for (int i = 0; i < 10; i++) {
    thread *t = new thread(example_function);
    t->join();
    delete t;
}

In any version of C++11 onwards it is recommended you use std::unique_ptr in these cases:

The most recommended form is:

auto t{std::make_unique<std::thread>(example_function)};

Which is almost equivalent to:

std::unique_ptr<std::thread> t(new std::thread(example_function));

A std::unique_ptr is an object that has operator overloading to behave a lot like a pointer with the difference of deleting the thing it points to (if anything) at the end of its life-time.

Upvotes: 0

user0042
user0042

Reputation: 8018

Here

thread *t = new thread(example_function);

you already loose the formerly allocated thread instance and have a memory leak.

join() doesn't free the allocated memory, but picks up the asynchonously ended function.

Upvotes: 0

Related Questions