Corrupted output with C++, cin, cout, threads and sync_with_stdio

前端 未结 1 925
隐瞒了意图╮
隐瞒了意图╮ 2021-01-31 12:10

I am trying to make a program in C++ to process a lot of packets in the fastest way possible. All the packets come from the standard should be read as fast as possible, sent to

相关标签:
1条回答
  • 2021-01-31 12:40

    I finally found the culprit. If you search for Internet a lot of sites recommends using the sync_with_stdio call, but they don't talk about threads.

    Other sites talk about iostreams and threads, like this one, but that doesn't explain why I was getting corrupted output when I was using std::cin in only one thread, and std::cout in its own thread too.

    The problem is that internally, the std::cin input thread was calling to std::cout to flush its buffer, but as the streams where not synchronized with mutex or something similar, the output was corrupted. Why should I synchronized the buffers if they are doing different things? Why std::cin was messing with std::cout?

    In C++, by default, the standard streams cin, cerr and clog are tied to cout. What does this mean? It means that when you try to read from cin, first it will force a flush to cout. Sometimes this is something useful as you can read here.

    But in my case, this was causing some serious issues, so, how to untie the streams?. It's very easy using the tie method:

    std::ios_base::sync_with_stdio(false);
    
    std::cin.tie(nullptr);
    std::cerr.tie(nullptr);
    

    Or if your compiler doesn't support C++11:

    std::ios_base::sync_with_stdio(false);
    
    std::cin.tie(static_cast<ostream*>(0));
    std::cerr.tie(static_cast<ostream*>(0));
    

    With this changes my output it's now correct:

    Packet id = 1
    Packet id = 2
    Packet id = 3
    Packet id = 4
    Packet id = 5
    Packet id = 6
    Packet id = 7
    Packet id = 8
    Packet id = 9
    Packet id = 10
    

    And as it avoids doing a flush every time std::cin is used, it's faster too :-)

    0 讨论(0)
提交回复
热议问题