1

I would like to know if the following code is thread-safe

void use_value(int i, unique_ptr<vector<int>> v);
for (int i = 0; i < 10; i++){
    unique_ptr<vector<int>> ptr = make_unique<vector<int>>(10);
    // ...
    // Here, the vector pointed to by ptr will be filled with specific values for each thread.
    // ....
    thread(
        [i, &ptr](){
            use_value(i, move(ptr));
        }
    );
}

Thank you

Ahmad Siavashi
  • 979
  • 1
  • 12
  • 29
  • Perhaps this is not your real code, but this example program will terminate after the first iteration of the loop, as the `std::thread` is [destroyed while still in a joinable state](http://en.cppreference.com/w/cpp/thread/thread/~thread). – Oktalist Aug 07 '16 at 13:34
  • @Oktalist you are right, it is not the real code; but I got interested in the point. You mean the newly created thread, because of RAII? – Ahmad Siavashi Aug 07 '16 at 20:52
  • `std::thread` is not a thread, it manages a thread. `thread([i, &ptr](){use_value(i, move(ptr));});` constructs a temporary `std::thread` which is immediately destroyed after the last `;`. Destroying an initialized `std::thread` without first calling `join()` or `detach()` will result in premature program termination. You need to move (or emplace construct) the `std::thread` somewhere else so it's not immediately destroyed, which is what your real code presumably already does. – Oktalist Aug 08 '16 at 14:03
  • @Oktalist Yes, that's correct. Thank you. – Ahmad Siavashi Aug 09 '16 at 05:50

1 Answers1

4

It's undefined behavior. You don't know when the lambda body will be called. So that ptr you capture by reference can very well be out of scope by then, the resource destructed, and you are left with a dangling reference.

You should "move-capture" the ptr (or better yet, just the vector) into the lambda, if you have access to c++14.

If you move (or copy) the vector, your code will be thread safe.

Community
  • 1
  • 1
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458