c++ - Boost asio 与标准输入混淆?

标签 c++ boost pipe boost-asio

该程序从 stdin 读取(通过 iostream)并写入 stdout(通过 boost/asio):

#include <boost/asio.hpp>
#include <cassert>
#include <iostream>
#include <string>

boost::asio::io_service io_service;
boost::asio::posix::stream_descriptor out(io_service, ::dup(STDOUT_FILENO));
std::string line = "";

static void handler(
    boost::system::error_code const &,
    std::size_t
) {
    assert(std::getline(std::cin, line));
    line += "\n";
    async_write(out, boost::asio::buffer(line), handler);
}

int main()
{
    async_write(out, boost::asio::buffer(line), handler);
    io_service.run();
}

构建:g++ -std=gnu++1y -O0 -g3 -o out in.cxx -lboost_system -lboost_thread

运行:猫 | ./out

输出:

foo [TERMINAL INPUT]
foo
bar [TERMINAL INPUT]
cat: -: Resource temporarily unavailable
bar
out: in.cxx:14: void handler(const boost::system::error_code&, std::size_t): Assertion `std::getline(std::cin, line)' failed.
Aborted (core dumped)

catwrite() 获取一个 EAGAIN 到其标准输出,将其视为错误,并关闭管道。反过来,getline() 失败并且程序中止。

这看起来 asio 正在将程序的标准输入(这是 cat 的标准输出,请参阅 Strange exception throw - assign: Operation not permitted )设置为非阻塞。但它没有明显的理由这样做,因为它仅在标准输出上运行。

如果我猜对了,这是 asio 中的一个错误吗?有解决办法吗?

libboost1.58-dev/xenial-updates,now 1.58.0+dfsg-5ubuntu3.1 amd64 [installed]
g++/xenial,now 4:5.3.1-1ubuntu1 amd64 [installed]

最佳答案

您调用 Undefined Behaviour这里:

async_write(out, boost::asio::buffer(string + "\n"), handler);

由于缓冲区是一个局部变量,因此当 handler 退出时,在异步写入操作有机会运行之前,它将被销毁。

编辑实际上,即使变量不是本地变量,+ "\n" 也会使其成为临时变量!

以下是针对这个简单程序的建议修复:

Live On Coliru

#include <boost/asio.hpp>
#include <cassert>
#include <iostream>
#include <string>

boost::asio::io_service io_service;
boost::asio::posix::stream_descriptor out(io_service, ::dup(STDOUT_FILENO));
std::string input_buffer;

static void handler(boost::system::error_code /*error*/, std::size_t /*bytes_transferred*/) {
    if (std::getline(std::cin, input_buffer)) {
        input_buffer += "\n";
        async_write(out, boost::asio::buffer(input_buffer), handler);
    }
}

int main() {
    async_write(out, boost::asio::buffer(""), handler);
    io_service.run();
}

我不确定这是否能解决您的所有问题,但至少您需要修复它,以便能够完全推理您的程序

关于c++ - Boost asio 与标准输入混淆?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42505574/

相关文章:

c - 使用 C 在 Linux Shell 中实现管道

c++ - boost序列化库中的<<和&有什么区别?

c++ - (Closed) C++ & Direct3D 9 - 如何绘制格式化文本? (如 printf 等)

c++ - 限定名称的重载解析

c++ - boost 类包装指针的序列化

linux - 管道组件在shell中的执行顺序

c++ - char == char 是否将两个操作数隐式转换为 int?

ubuntu - 在 Ubuntu : make can't find Boost's include files 上构建 Caffe

c++ - 如何简化boost::static_vistor的派生类

node.js - NodeJS - 管道多个 FFMPEG 进程