4

I try to use C++11 theading library using g++ 4.7. First I have a question: is it expected for a next release to not be required to link by hand the pthread library ?

So my program is :

#include <iostream>
#include <vector>
#include <thread>

void f(int i) {
    std::cout<<"Hello world from : "<<i<<std::endl;
}

int main() {
    const int n = 4;
    std::vector<std::thread> t;
    for (int i = 0; i < n; ++i) {
        t.push_back(std::thread(f, i));
    }
    for (int i = 0; i < n; ++i) {
        t[i].join();
    }
    return 0;
}

I compile with:

g++-4.7 -Wall -Wextra -Winline -std=c++0x -pthread -O3 helloworld.cpp -o helloworld

And it returns:

Hello world from : Hello world from : Hello world from : 32
2
pure virtual method called

terminate called without an active exception
Erreur de segmentation (core dumped)

What is the problem and how to solve it ?

UPDATE:

Now using mutex:

#include <iostream>
#include <vector>
#include <thread>
#include <mutex>

static std::mutex m;

void f(int i) {
    m.lock();
    std::cout<<"Hello world from : "<<i<<std::endl;
    m.unlock();
}

int main() {
    const int n = 4;
    std::vector<std::thread> t;
    for (int i = 0; i < n; ++i) {
        t.push_back(std::thread(f, i));
    }
    for (int i = 0; i < n; ++i) {
        t[i].join();
    }
    return 0;
}

It returns :

pure virtual method called
Hello world from : 2
terminate called without an active exception
Abandon (core dumped)

UPDATE 2: Hum... It works with my default GCC (g++4.6) but it fails with the version of gcc I compiled by hand (g++4.7.1). Was there an option I forgot to compile g++ 4.7.1 ?

Vincent
  • 57,703
  • 61
  • 205
  • 388
  • 1
    How does the stackdump look like? Use `gdb helloworld core` and then `bt`. – Olaf Dietsche Dec 26 '12 at 14:55
  • I can compile your program just fine with `g++-4.7 main.cpp -std=c++11` – JaredC Dec 26 '12 at 14:56
  • @JaredC I believe Vincent is talking about a run-time problem, not a compilation issue. – jogojapan Dec 26 '12 at 14:59
  • @jogojapan agreed. but he asked about linking in pthread by hand too. – JaredC Dec 26 '12 at 15:00
  • 1
    @JaredC Oh right, but that is still necessary. If you use C++11 multithreading and GCC and fail to use the `-pthread` option (which is more than linking with the posix thread library), you will run into problems at run-time sooner or later -- even if it compiles alright. – jogojapan Dec 26 '12 at 15:01
  • You don't need to lock std::cout. Then, why it runs fine on ideone.com - http://ideone.com/xrGhB6 – SChepurin Dec 26 '12 at 15:09
  • I updated my question (maybe I forgot an option to compile g++?) – Vincent Dec 26 '12 at 15:23
  • @Vincent: put -lpthread (and not -pthread) at the end of the command line. – user1284631 Dec 26 '12 at 15:31
  • @Vincent: and use the compiler flag: -std=gnu++11 instead of c++0x – user1284631 Dec 26 '12 at 15:32
  • `g++-4.7 -Wall -Wextra -Winline -std=gnu++11 -O3 helloworld.cpp -o helloworld -lpthread` -> same problem – Vincent Dec 26 '12 at 15:34
  • @Vincent: this is what I use (Linux, g++ 4.7.2): g++ threadtest2.cpp -std=gnu++11 -lpthread – user1284631 Dec 26 '12 at 15:34
  • @Vincent: for me, it works, I obtain this: Hello world from : 3 Hello world from : 2 Hello world from : 1 Hello world from : 0 – user1284631 Dec 26 '12 at 15:35
  • @Vincent: do you have more than one compiler version installed on your machine? Are you sure that you are using the right -lstdc++ library, ie. each one to the respective compiler? – user1284631 Dec 26 '12 at 15:44
  • Yes I have g++ 4.6 (by default) and g++ 4.7.1 (compiled myself). But I never use options with the linking of c++ library. How to know whether I have 2 versions of stdc++ ? – Vincent Dec 26 '12 at 15:53
  • @Vincent: see this, maybe it helps: http://stackoverflow.com/q/2085427/1284631 – user1284631 Dec 26 '12 at 16:03

1 Answers1

0

General edit:

In order to prevent use of cout by multiple threads simultaneously, that will result in character interleaving, proceed as follows:

1) declare before the declaration of f():

static std::mutex m;

2) then, guard the "cout" line between:

m.lock();
std::cout<<"Hello world from : "<<i<<std::endl;
m.unlock();

Apparently, linking against the -lpthread library is a must, for some unclear reasons. At least on my machine, not linking against -lpthread results in a core dump. Adding -lpthread results in proper functionality of the program.

The possibility of character interleaving if locking is not used when accessing cout from different threads is expressed here:

https://stackoverflow.com/a/6374525/1284631

more exactly: "[ Note: Users must still synchronize concurrent use of these objects and streams by multiple threads if they wish to avoid interleaved characters. — end note ]"

OTOH, the race condition is guaranteed to be avoided, at least in the C++11 standard (beware, the gcc/g++ implementation of this standard is still at experimental level).

Note that the Microsoft implementation (see: http://msdn.microsoft.com/en-us/library/c9ceah3b.aspx credit to @SChepurin) is stricter than the standard (apparently, it guarantees character interleaving is avoided), but this might not be the case for the gcc/g++ implementation.

This is the command line that I use to compile (both updated and original code versions, everything works well on my PC):

g++ threadtest.cpp -std=gnu++11 -lpthread -O3

OTOH, without the -lpthread, it compiles but I have a core dump (gcc 4.7.2 on Linux 64).

I understand that you are using two different versions of the gcc/g++ compiler on the same machine. Just be sure that you use them properly (not mixing different library versions).

Community
  • 1
  • 1
user1284631
  • 4,446
  • 36
  • 61
  • Pulled from another SO thread, it looks like cout in C++11 is thread safe: http://stackoverflow.com/questions/6374264/is-cout-synchronized-thread-safe – Ryan Guthrie Dec 26 '12 at 15:04
  • @Vincent: add the -lpthread library to your compilation line. This will solve the issue, I just made the test on my machine. – user1284631 Dec 26 '12 at 15:14
  • "The iostream classes follow the same rules as the other classes, with one exception. It is safe to write to an object from multiple threads. For example, thread 1 can write to cout at the same time as thread 2. However, this can result in the output from the two threads being intermixed." See MSDN - http://msdn.microsoft.com/en-us/library/c9ceah3b.aspx – SChepurin Dec 26 '12 at 15:21
  • @SChepurin: True, there is no racing possible. However, Character interleaving may occur. I will update the answer. – user1284631 Dec 26 '12 at 15:37
  • @RyanGuthrie: you are right, I updated the answer. However, locking is still good to have to avoid character interleaving at the output. – user1284631 Dec 26 '12 at 15:41
  • @axeoth - Not character interleaving. "Output intermixed" means the sequence of threads output can be wrong, like - 4 2 3 1 0. – SChepurin Dec 26 '12 at 15:43
  • 1
    @SChepurin: quoting from the standard quoted inside the linked answer: "[ Note: Users must still synchronize concurrent use of these objects and streams by multiple threads if they wish to avoid interleaved characters. — end note ]" – user1284631 Dec 26 '12 at 15:45
  • @SChepurin: The Microsoft implementation might be stricter than the standard, but is not guaranteed to be followed by the g++ compiler that the OP is using. – user1284631 Dec 26 '12 at 15:49
  • @axeoth - Thanks, for pointing on this. But this particular sample is not the case. Still, it would be safer to follow the Standard's note. – SChepurin Dec 26 '12 at 15:55
  • 1
    @axeoth, this solution does not use exception safe patterns. You normally should not `.lock()` manually. Have a look at http://en.cppreference.com/w/cpp/thread/lock_guard – Johan Lundberg Dec 26 '12 at 21:54
  • @JohanLundberg: thank you for pointing this out. However, why the solution, as it is, does not work for the OP? It is because of that lock? Normally, cout should not trigger a core dump, even without the lock, it should only garble output. – user1284631 Dec 26 '12 at 22:38