Asked  6 Months ago    Answers:  5   Viewed   22 times

In general I assume that streams are not synchronized, it is up to the user to do appropriate locking. However, do things like cout get special treatment in the standard library?

That is, if multiple threads are writing to cout can they corrupt the cout object? I understand that even if synchronized you'd still get randomly interleaved output, but is that interleaving guaranteed. That is, is it safe to use cout from multiple threads?

Is this vendor dependent? What does gcc do?


Important: Please provide some kind of reference for your answer if you say "yes" since I need some kind of proof of this.

My concern is also not about the underlying system calls, those are fine, but the streams add a layer of buffering on top.

 Answers

82

The C++03 standard does not say anything about it. When you have no guarantees about the thread-safety of something, you should treat it as not thread-safe.

Of particular interest here is the fact that cout is buffered. Even if the calls to write (or whatever it is that accomplishes that effect in that particular implementation) are guaranteed to be mutually exclusive, the buffer might be shared by the different threads. This will quickly lead to corruption of the internal state of the stream.

And even if access to the buffer is guaranteed to be thread-safe, what do you think will happen in this code?

// in one thread
cout << "The operation took " << result << " seconds.";

// in another thread
cout << "Hello world! Hello " << name << "!";

You probably want each line here to act in mutual exclusion. But how can an implementation guarantee that?

In C++11, we do have some guarantees. The FDIS says the following in §27.4.1 [iostream.objects.overview]:

Concurrent access to a synchronized (§27.5.3.4) standard iostream object’s formatted and unformatted input (§27.7.2.1) and output (§27.7.3.1) functions or a standard C stream by multiple threads shall not result in a data race (§1.10). [ Note: Users must still synchronize concurrent use of these objects and streams by multiple threads if they wish to avoid interleaved characters. — end note ]

So, you won't get corrupted streams, but you still need to synchronize them manually if you don't want the output to be garbage.

Tuesday, June 1, 2021
 
danjah
answered 6 Months ago
72

There's no sequence point with the << operator so the compiler is free to evaluate either dequeue function first. What is guaranteed is that the result of the second dequeue call (in the order in which it appears in the expression and not necessarily the order in which it is evaluated) is <<'ed to the result of <<'ing the first (if you get what I'm saying).

So the compiler is free to translate your code into some thing like any of these (pseudo intermediate c++). This isn't intended to be an exhaustive list.

auto tmp2 = myQueue.dequeue();
auto tmp1 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
tmp3 << tmp2;

or

auto tmp1 = myQueue.dequeue();
auto tmp2 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
tmp3 << tmp2;

or

auto tmp1 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
auto tmp2 = myQueue.dequeue();
tmp3 << tmp2;

Here's what the temporaries correspond to in the original expression.

cout << myQueue.dequeue() << myQueue.dequeue();
|       |               |    |               |
|       |____ tmp1 _____|    |_____ tmp2 ____|
|                       |
|________ tmp3 _________|
Tuesday, June 1, 2021
 
CodeCaster
answered 6 Months ago
38

Problems:

  1. You have some missing #includes, which probably caused your initial compiler errors.
  2. You have a simple syntax error with your if statement.
  3. Using the stream extraction operator will never yield a string with whitespace inside of it.

The following should work as you expect:

#include "stdafx.h"
#include <iostream>
#include <ostream>
#include <string>

using namespace std;

int main()
{
    cout << "Input your name please?" << endl;

    string name;
    getline(cin, name);
    if (name == "Bart Simpson")
    {
        cout << "You have been very naughty" << endl;
    }

    return 0;
}

(You need to include string for std::string and std::getline, and ostream for std::endl.)

Thursday, September 2, 2021
 
showstealer
answered 3 Months ago
45

MSVC has the huge advantage of coming with an IDE that has no equals under Windows, including debugger support.

The probably best alternative for MinGW would be Code::Blocks, but there are worlds in between, especially regarding code completion and the debugger.

Also, MSVC lets you use some proprietary Microsoft stuff (MFC, ATL, and possibly others) that MinGW has no support for, and makes using GDI+ and DirectX easier and more straightforward (though it is possible to do both with MinGW).

Cygwin, as mentioned in another post, will have extra dependencies and possible license issues (the dependency is GPL, so your programs must be, too). MinGW does not have any such dependency or issue.

MinGW also compiles significantly slower than MSVC (though precompiled headers help a little).

Despite all that, GCC/MinGW is an entirely reliable quality compiler, which in my opinion outperforms any to date available version of MSVC in terms of quality of generated code.
This is somewhat less pronounced with the most recent versions of MSVC, but still visible. Especially for anything related to SSE, intrinsics, and inline assembly, GCC has been totally anihilating MSVC ever since (though they're slowly catching up).

Standards compliance is a lot better in GCC too, which can be a double-edged sword (because it can mean that some of your code won't compile on the more conforming compiler!), as is C++11 support.

MinGW optionally also supports DW2 exceptions, which are totally incompatible with the "normal" flavour and take more space in the executable, but on the positive side are "practically zero cost" in runtime.

Friday, September 3, 2021
 
Christopher Francisco
answered 3 Months ago
80

I must say that you found some nice corner case that makes compilers crazy :-) For me gcc 4.7.2 and 4.8 crashed during compilation. However clang (top version) compiled whole code fine but was using 2.4GB RAM. The problem seems to be connected to ternaty operator for '.' check. If you remove it and comment real number tests in main() everything compiles fine like a blast.

So answering your question you probably do not miss anything and gcc and clang need to probably revise their implementaion based on your case.

Saturday, October 30, 2021
 
k to the z
answered 1 Month ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share