该程序从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
运行:cat | ./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
从EAGAIN
获取write()
到其标准输出,将其视为错误,然后关闭管道。反过来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]
答案 0 :(得分:1)
您在此处调用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();
}
我不确定这会解决您的所有问题,但至少您需要修复它以便能够推理您的程序