3

I have following block of code, what I expected is the i inside the lambda capture list is passed by value and the i be outputted should be different.

However, the actual result is the output 20 lines of 19 is completed.

I tried to change the this line std::thread t([&func](){ to std::thread t([func](){, the output could print different i value.

My question is why std::thread t([&func](){ and std::thread t([func](){ will lead the different output value of i?

void DoSomething(std::function<void()> func)
{
    std::thread t([&func](){
        //do something
        sleep(1);
        if (func)
            func();
    });
    t.detach();
}

int main(int argc, const char * argv[]) {
    std::mutex mtx;
    for (int i = 1 ; i < 20; i ++) {
        DoSomething([i, &mtx](){
            std::unique_lock<std::mutex> lock(mtx);
            std::cout << i << " is completed" << std::endl;;
        });
    }
    sleep(10);
}

3 Answers 3

2

You're capturing a reference to DoSomething's parameter, func.
By the time your thread executes, that parameter's lifetime has ended so you have a dangling reference and using it is undefined.

Sign up to request clarification or add additional context in comments.

2 Comments

is that means the func passed to the DoSomething carry the information about the capture list?
@2power10 I'm not sure what you're asking. If you're capturing by reference you need to ensure that the referenced object is valid when you use it, otherwise the program is undefined. Capturing by value is the correct thing to do here.
0

Thread object t in DoSomething() receives a reference to the func object which is passed as by value. When func() is executed, it might be waiting for the mutex by the call std::unique_lock<std::mutex> lock(mtx); In the meantime t.detach() will be invoked and the function would have exited by destroying the by value parameter func. This will result in dangling reference as said by @molbidnilo.

The problem can be solved by calling t.join(); instead of t.detach().

1 Comment

use t.join() will block the DoSomething, and that's why I use t.detach() here. I think the problem can be solved by capturing the func by value instead of reference.
0

if you use t.detach(), the thread is running independently, now that you pass function object by reference, so if the function object was destroyed when the independent thread is trying to refer, wouldn't that cause crash of the program. but if you pass the function object by value, this issue is solved. i tested your code in my machine, it crashed when using passed function object by reference.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.