C++、cin、cout、threads 和sync_with_stdio 的输出损坏

2023-12-29

我正在尝试用 C++ 编写一个程序,以尽可能最快的方式处理大量数据包。来自标准的所有数据包都应尽快读取,发送到池中的一个线程进行处理,然后处理到将数据包写入标准输出的输出线程。

当您在 C++ 中使用标准输入和输出时,建议在任何输入或输出之前调用std::ios_base::sync_with_stdio(假) http://en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio功能。在某些环境中,这可以实现很大的加速,尽管您应该避免在调用后使用标准 C 函数进行输入/输出。

嗯,这似乎在单线程中完美工作。但正如我所说,我的目的是使用一个线程用于输入,一个线程用于输出,多个线程用于并行处理。我观察到输出存在一些问题。这是输出线程(非常简化):

void PacketDispatcher::thread_process_output(OutputQueue& output_queue) {
    std::vector<Packet> packet_list;
    while(output_queue.get(packet_list)) {
        for (const auto& packet: packet_list) {
            std::cout << "Packet id = " << packet.id << "\n";
        }
    }
    std::cout.flush();
}

如果我用过标准::endl代替"\n"损坏较少,但 std::endl 强制刷新流,在这种情况下影响性能(并且问题没有解决,只是最小化)。

这是程序中使用 std::cout 的唯一点,但是如果我调用std::ios_base::sync_with_stdio(假) http://en.cppreference.com/w/cpp/io/ios_base/sync_with_stdio在程序开始时,我得到了明显的加速,但我的输出总是以某种方式损坏:

Packet id = Packet id = 4
Packet id = 5
Packet id = 6
Packet id = 7
Packet id = 8
Packet id = 9
Packet id = 10

那么,问题出在哪里呢? C++ 不能使用快速标准输入/输出进行多线程处理吗?


我终于找到了罪魁祸首。如果您搜索互联网,很多网站都建议使用sync_with_stdio 调用,但他们不讨论线程。

其他站点讨论 iostreams 和线程,例如this one https://stackoverflow.com/questions/6374264/is-cout-synchronized-thread-safe,但这并不能解释为什么我在使用 std::cin 时输出损坏只有一个线程和 std::cout也在它自己的线程中.

问题在于,在内部, std::cin 输入线程正在调用 std::cout 来刷新其缓冲区,但由于流未与互斥体或类似的东西同步,因此输出已损坏。如果缓冲区正在做不同的事情,为什么我应该同步它们?为什么 std::cin 会搞乱 std::cout ?

在 C++ 中,默认情况下,标准流 cin、cerr 和 clog 与 cout 绑定。这是什么意思?这意味着当您尝试从 cin 读取数据时,它首先会强制刷新 cout。有时这是有用的,你可以阅读here https://stackoverflow.com/questions/2704752/flushing-of-cout-prior-to-reading-input-using-cin-why.

但就我而言,这引起了一些严重的问题,那么,如何解开流呢?使用起来非常简单领带法 http://en.cppreference.com/w/cpp/io/basic_ios/tie:

std::ios_base::sync_with_stdio(false);

std::cin.tie(nullptr);
std::cerr.tie(nullptr);

或者,如果您的编译器不支持 C++11:

std::ios_base::sync_with_stdio(false);

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

通过此更改,我的输出现在是正确的:

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

而且由于它避免了每次使用 std::cin 时都进行刷新,因此速度也更快:-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++、cin、cout、threads 和sync_with_stdio 的输出损坏 的相关文章

  • 为什么模板类的静态成员不唯一

    看一下下面的代码 include
  • Xamarin 测试记录器选项有错误。无法记录自动化测试

    选项 gt Xamarin gt Xamarin Test Recorder 中的所有设置都有错误 我的桌面上安装了 Visual Studio 2015 企业版 以及 Xamarin 和 Xamarin Test Recorder 插件
  • 如何将动态数据写入 MVC 3 Razor 中的页面布局?

    我有带有 Razor 引擎的 MVC 3 C 项目 将动态数据写入 Layout cshtml 的方法和最佳实践是什么 例如 也许我想在网站的右上角显示用户名 该名称来自会话 数据库或基于用户登录的任何内容 更新 我也在寻找将某些数据渲染到
  • Python 相当于 Bit Twiddling Hacks 中的 C 代码?

    我有一个位计数方法 我正在尝试尽可能快地实现 我想尝试下面的算法位摆弄黑客 http graphics stanford edu seander bithacks html CountBitsSetParallel 但我不知道 C 什么是
  • C 中的双重否定:是否保证返回 0/1?

    Is x 标准保证返回0 1 请注意 我是not询问 C 其中定义了 bool 类型 是的 在 C99 中 请参阅 6 5 3 3 4 逻辑非运算符的结果 是0如果其操作数的值比较 不等于0 1如果其操作数的值比较等于 0 结果具有类型in
  • 在关键服务器上对字符串进行内存受限的外部排序,并合并和计算重复项(数十亿个文件名)

    我们的服务器生成如下文件 c521c143 2a23 42ef 89d1 557915e2323a sign xml在其日志文件夹中 第一部分是GUID 第二部分是名称模板 我想计算具有同名模板的文件的数量 例如 我们有 c521c143
  • 公共基类打破了元组的空基类优化

    gcc 4 7 1 对元组进行空基类优化 我认为这是一个非常有用的功能 然而 这似乎有一个意想不到的限制 include
  • Xcode 新手无法用 C++ 打开文件?

    我一直在我参加的课程中使用 Windows 但我正在尝试运行基本代码来弄清楚如何从 Xcode 上的文件打开 关闭 输入 输出 而我通常在 Visual Studio 上使用的代码不是不知道为什么 谢谢 include
  • Python time.sleep - 永不醒来

    我认为这将是那些简单的问题之一 但它让我感到困惑 停止媒体 我是对的 找到了解决方案 查看答案 我正在使用 Python 的单元测试框架来测试多线程应用程序 很好而且很直接 我有 5 个左右的工作线程监视一个公共队列 以及一个为它们制作工作
  • 哪个更快?按引用传递与按值传递 C++

    我认为按引用传递应该比按值传递更快 因为计算机不复制数据 它只是指向数据的地址 但是 请考虑以下 C 代码 include
  • VS C# 中的依赖地狱,找不到依赖项

    我创建了一个图表 C 库 我们称之为chartlibrary 它本身依赖于多个第三方 dll 文件 在另一个可执行项目中 我们称之为chartuser 我参考了chartlibrary项目 两个项目位于 Visual Studio 中的同一
  • C# SignalR 异常 - 连接在收到调用结果之前开始重新连接

    我正在开发 2 个应用程序 第一个是 C 控制台应用程序 另一个是 Asp net Web 应用程序 我正在使用 SignalR 连接两者 这是我的 C 控制台应用程序 客户端 public class RoboHub public sta
  • 为什么在 C++ 类中的数据成员上使用像 m_ 这样的前缀?

    许多 C 代码使用语法约定来标记数据成员 常见的例子包括 m memberName对于公共成员 在所有使用公共成员的情况下 memberName对于私人会员或所有会员 其他人尝试强制使用this gt member每当使用数据成员时 根据我
  • 提升shared_from_this<>()

    有人可以用几句话概括一下如何提升shared from this lt gt 应该使用智能指针 特别是从使用绑定函数在 io service 中注册处理程序的角度来看 编辑 一些回复要求提供更多背景信息 基本上 我正在寻找 陷阱 即人们使用
  • 为什么 getch 不可移植?

    是什么使得 getch 本质上无法作为标准 C 函数包含在内 对于控制台界面来说 它是如此直观和优雅 如果没有它 要求输入单个字符总是会产生误导 因为用户可以输入多个键 更糟糕的是 您经常需要确保在读取控制台输入后清除标准输入 这甚至不是作
  • 曲线/路径骨架二值图像处理

    我正在尝试开发一个可以处理图像骨架的路径 曲线的代码 我想要一个来自两点之间骨架的点向量 该代码在添加一些点后结束 我没有找到解决方案 include opencv2 highgui highgui hpp include opencv2
  • 查找文本文件中每行的行大小

    如何计算每行中的字符或数字数量 是否有类似 EOF 的东西更像是行尾 您可以遍历行中的每个字符并不断增加计数器直到行尾 n 遇到 确保以文本模式打开文件 r 而不是二进制模式 rb 否则流不会自动将不同平台的行结束序列转换为 n 人物 这是
  • 使用 ImageResizer 获取图像尺寸的最佳方法

    我正在将现有的 MVC 4 网站从自制用户文件上传切换为在上传时使用 ImageResizer 调整文件大小 我在文档中看到我不应该使用 System Drawing 但我无法找出任何其他获取图像尺寸的方法 尺寸是来自原始图像还是调整大小的
  • 从最大到最小的3个整数

    我是 C 初学者 我使用 编程 使用 C 的原理与实践 第二版 问题如下 编写一个程序 提示用户输入三个整数值 然后以逗号分隔的数字顺序输出这些值 如果两个值相同 则应将它们排列在一起 include
  • C#“var”关键字在 VB.NET 中的等价物是什么?

    例如 我如何获得 VB NET静态类型局部变量是static赋值右侧的表达式的类型 像这样 Dim http msdn microsoft com en us library 7ee5a7s1 aspx我的变量 3 你还需要 选项推断 ht

随机推荐