奇怪的异常抛出 - 赋值:不允许操作

dar*_*enn 5 c++ boost boost-asio

我想从cin做异步读取因此我有一段代码

client.h

...
boost::asio::posix::stream_descriptor input;
boost::asio::streambuf input_buffer
Run Code Online (Sandbox Code Playgroud)

client.cpp

Client::Client(int argc, char **argv, boost::asio::io_service &io_service)
    : tcp_socket(io_service)
    , udp_socket(io_service)
    , input(io_service, ::dup(STDIN_FILENO))
{
    ...
    read_std_input();
}

void Client::read_std_input() {
    async_read_until(input, input_buffer, '\n',
                     boost::bind(&Client::handle_std_read, this,
                                 boost::asio::placeholders::error,
                                 boost::asio::placeholders::bytes_transferred));
}
Run Code Online (Sandbox Code Playgroud)

问题是:当我以正常方式[./client]运行我的客户端然后通过命令输入一些东西时,它就像魅力一样.但是,当我通过[./client <test]运行它时会抛出:

在抛出'boost :: exception_detail :: clone_impl的实例后终止调用

'what():assign:不允许操作中止

你知道问题可能是什么吗?谢谢!

Tan*_*ury 9

Boost.Asio的POSIX面向流的描述符显然不支持常规文件.因此,如果test是一个普通文件,那么./client < test会导致posix::stream_descriptor::assign()尝试分配失败时STDIN_FILENOstream_descriptor.该文件规定:

Boost.Asio包括添加的类,允许在POSIX文件描述符上执行同步和异步读写操作,例如管道,标准输入和输出以及各种设备(但不是常规文件).

考虑通过管道传递test文件的内容client.

$ cat test | ./client
Run Code Online (Sandbox Code Playgroud)

这是一个完整的示例程序和演示:

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

void handle_read(
  const boost::system::error_code& error,
  std::size_t bytes_transferred
)
{
  std::cout << "read " << bytes_transferred << " bytes with "
            << error.message() << std::endl;
}

int main()
{
  boost::asio::io_service io_service;
  boost::asio::posix::stream_descriptor input(io_service);

  // Assign STDIN_FILENO to the stream_descriptor.  It will support
  // pipes, standard input and output, and various devices, but NOT
  // regular files.
  boost::system::error_code error;
  input.assign(STDIN_FILENO, error);
  if (error)
  {
    std::cerr << error.message() << std::endl;
    return -1;
  }

  boost::asio::streambuf input_buffer;
  async_read_until(input, input_buffer, '\n', &handle_read);
  io_service.run();
}
Run Code Online (Sandbox Code Playgroud)

示范

$ ./client
testing standard inputenter
read 23 bytes with Success
$ echo "this is a test" > test
$ ./client < test
Operation not permitted
$ cat test | ./client
read 15 bytes with Success