2

the following program give some strange compile/run-time behavior when compiled with Visual Studio 2013:

#include "stdafx.h"
#include <thread>
#include <chrono>
#include <iostream>

int main()
{

    {//works
        std::thread([](){
            std::cout << " thread running1\n";
        });
    }

    {//compile but synstax error exist
        auto func = [](){
            std::cout << " thread running2\n";
        };

        std::thread(fun); //fun is not defined
    }


    {//compile, see next block for mystery compile error
        auto func = [](){
            std::cout << " thread running2\n";
        };

        std::thread tmp(func); 
    }

    {//does not compile and don't know why
        auto func = [](){
            std::cout << " thread running2\n";
        };

        std::thread(func); //error C2371: 'func' : redefinition; different basic types
    }

    return 0;
}

When this program work, there may crash as there is race condition between the thread. The main thread may end before the other threads.

Does anybody know why the second block and last block does not work?

Praetorian
  • 106,671
  • 19
  • 240
  • 328
Johan
  • 575
  • 5
  • 21

1 Answers1

3
{//compile but synstax error exist
    auto func = [](){
        std::cout << " thread running2\n";
    };

    std::thread(fun); //fun is not defined
}

There's no syntax error here, std::thread(fun) default constructs an std::thread object named fun.

The error in the last block is because of the same reason

std::thread(func); //error C2371: 'func' : redefinition; different basic types

You're trying to default construct an std::thread object named func above and that's an error because a lambda of the same name already exists in the same scope. To pass the lambda to the thread constructor use braces instead

 std::thread{func};

Now, after you've made these changes your code will compile but will fail at runtime because the thread objects in blocks 1, 3 & 4 are all going to call std::terminate (of course, your program terminates when the first thread object calls std::terminate so the other two doing that is a moot point).

The reason that happens is that you have joinable threads in all 3 blocks and if the destructor of such a thread object runs, std::terminate will be called. To avoid that you must call thread::join (you could also call thread::detach but don't do that).

For instance

{//works
    std::thread([](){
        std::cout << " thread running1\n";
    }).join();
}

Live demo

Community
  • 1
  • 1
Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • Where did the syntax changed in c++? My understanding was that std::thread(func); will create an unnamed object passing func to the constructor. Ps my program works now :-) – Johan Mar 02 '15 at 08:29
  • @Johan It's always been this way. See [this answer](http://stackoverflow.com/a/6342009/241631); you can add even more pairs of parentheses if you like :) – Praetorian Mar 02 '15 at 08:36