该程序从 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)
cat
从 write()
获取一个 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"
也会使其成为临时变量!
以下是针对这个简单程序的建议修复:
#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/