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

时间:2014-05-12 16:35:16

标签: c++ boost boost-asio

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

client.h

...
boost::asio::posix::stream_descriptor input;
boost::asio::streambuf input_buffer

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));
}

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

  

在抛出一个实例后终止调用   “增强:: exception_detail :: clone_impl

     
    

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

  

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

4 个答案:

答案 0 :(得分:9)

Boost.Asio的POSIX面向流的描述符显然不支持常规文件。因此,如果test是常规文件,则./client < test在尝试将STDIN_FILENO分配给stream_descriptor时会导致posix::stream_descriptor::assign()失败。 documentation州:

  

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

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

$ cat test | ./client

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

#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();
}

示范

$ ./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

答案 1 :(得分:1)

Linux上的异步文件I / O仍然相当原始。尽管ASIO对异步文件I / O的支持在Windows中运行良好,但我在Linux上使用它并没有太多(运气)。

This is a previous SO question that provides some background on the issue

答案 2 :(得分:1)

Boost asio在Linux上使用epollby default does not support files

但有一种解决方法:如果您定义BOOST_ASIO_DISABLE_EPOLL,那么asio将恢复为select系统,文件将起作用。

答案 3 :(得分:0)

你可以试试这个最小的复制品吗?它适用于我的Ubuntu 64位盒子:

#include <boost/asio.hpp>
#include <boost/asio/posix/stream_descriptor.hpp>

#include <iostream>

int main()
{
    using namespace boost::asio;

    io_service io;
    posix::stream_descriptor input(io);

    input.assign(STDIN_FILENO);
    streambuf input_buffer;

    std::function<void()> loop = [&] {
        async_read_until(input, input_buffer, '\n', [&](boost::system::error_code ec, size_t) {
            if (ec) 
                std::cerr << ec.message();
            else {
                std::cout << "LOOP: '" << &input_buffer << "'\n";
                loop();
            }
        });
    };

    loop();
    io.run();
}

更新我想我可以重现问题 on Coliru :您能查看ulimit -a的输出吗?