【问题标题】:Boost asio resolver is unitializedBoost asio 解析器未初始化
【发布时间】:2020-09-11 19:00:32
【问题描述】:

我觉得问这个有点傻,因为我在这里发布的最小示例有效,但是当我将它作为我项目的一部分来实现时,我得到了一个 segfault。但我还是会继续问。

下面是我的代码

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

using boost::asio::ip::tcp;
using boost::asio::ip::udp;

class Transport
{
public:
  virtual bool connect() = 0;
  virtual void disconnect() = 0;
  virtual void read(boost::array<char, 4096> &buf, size_t &len) = 0;

  Transport(std::string address) : address_(address) {}

  void set_port(std::string port)
  {
    port_ = std::move(port);
  }

  std::string get_port()
  {
    return port_;
  }

  std::string get_host_ip()
  {
    return host_ip_;
  }

protected:
  std::string address_;
  std::string host_ip_;
  std::string port_;
  boost::asio::io_service io_service_;
};

class TCPTransport : public Transport
{
public:
    TCPTransport(std::string address) : Transport(address), socket_(io_service_) {}

    ~TCPTransport()
    {
      disconnect();
    }

    virtual bool connect()
    {
      try
      {
        std::cout << "io_service " << io_service_.stopped() << std::endl;
        tcp::resolver resolver(io_service_);
        tcp::resolver::query query(address_, port_);
        tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
        tcp::resolver::iterator end;

        boost::system::error_code error = boost::asio::error::host_not_found;
        while (error && endpoint_iterator != end)
        {
          socket_.close();
          socket_.connect(*endpoint_iterator++, error);
        }
        if (error)
        {
          throw boost::system::system_error(error);
        }
      }
      catch (std::exception& e)
      {
        std::cerr << e.what() << std::endl;
        return false;
      }
      return true;
    }

    virtual void disconnect()
    {
      std::cout << "disconnecting..." << std::endl;
      socket_.close();
    }

    void read(boost::array<char, 4096> &buf, size_t &len)
    {
      boost::system::error_code error;
      len = socket_.read_some(boost::asio::buffer(buf), error);
      if (error == boost::asio::error::eof)
        return; // Connection closed cleanly by peer.
      else if (error)
        throw boost::system::system_error(error); // Some other error.
    }

private:
    tcp::socket socket_;
};

class Writer
{
public:
  Writer(std::shared_ptr<Transport> &transport) : transport_(transport) {}

  void connect()
  {
    transport_->connect();
  }

  void start_read()
  {
    while(true)
    {
      size_t len;
      boost::array<char, 4096> buf;
      transport_->read(buf, len);
      // std::cout.write(buf.data(), len);
      std::cout << len << std::endl;
    }
  }

private:
  std::shared_ptr<Transport> transport_;
};

class ConnectionHolder
{
public:
  ConnectionHolder(std::shared_ptr<Transport> &transport) : transport_(transport) {}

  void init()
  {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    transport_->set_port("8000");
    transport_->connect();
    writer_ = std::make_shared<Writer>(transport_);
  }

  void start()
  {
    writer_->start_read();
  }

private:
  std::shared_ptr<Transport> transport_;
  std::shared_ptr<Writer> writer_;
};

int main(int argc, char* argv[])
{
  if (argc != 3)
  {
    std::cerr << "Usage: client <host>" << std::endl;
    return 1;
  }

  std::shared_ptr<Transport> transport = std::make_shared<TCPTransport>(argv[1]);
  ConnectionHolder holder(transport);
  // transport->set_port(argv[2]);
  holder.init();


  holder.start();

  return 0;
}

在创建 TCP 套接字之前,我需要请求 TCP 句柄。完成后,我可以开始从设备读取。上面附加的代码运行良好。但对于我的实际代码,valgrind 会抱怨:

==18714== Invalid read of size 8
==18714==    at 0x4C367E0: memmove (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18714==    by 0x12EDF1: boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>::create(addrinfo*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_resolver_iterator.hpp:99)
==18714==    by 0x12C657: boost::asio::detail::resolver_service<boost::asio::ip::tcp>::resolve(std::shared_ptr<void>&, boost::asio::ip::basic_resolver_query<boost::asio::ip::tcp> const&, boost::system::error_code&) (resolver_service.hpp:69)
==18714==    by 0x12989F: boost::asio::ip::resolver_service<boost::asio::ip::tcp>::resolve(std::shared_ptr<void>&, boost::asio::ip::basic_resolver_query<boost::asio::ip::tcp> const&, boost::system::error_code&) (resolver_service.hpp:113)
==18714==    by 0x126A8B: boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::ip::resolver_service<boost::asio::ip::tcp> >::resolve(boost::asio::ip::basic_resolver_query<boost::asio::ip::tcp> const&) (basic_resolver.hpp:102)
==18714==    by 0x12290D: TCPTransport::connect() (communication.h:99)
==18714==    by 0x137E3D: Interface::start_transmission() (pf_interface.cpp:94)
==18714==    by 0x117843: main (main.cpp:36)
==18714==  Address 0x10fe3fc000000000 is not stack'd, malloc'd or (recently) free'd
==18714== 
==18714== 
==18714== Process terminating with default action of signal 11 (SIGSEGV)
==18714==  General Protection Fault
==18714==    at 0x4C367E0: memmove (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18714==    by 0x12EDF1: boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>::create(addrinfo*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_resolver_iterator.hpp:99)
==18714==    by 0x12C657: boost::asio::detail::resolver_service<boost::asio::ip::tcp>::resolve(std::shared_ptr<void>&, boost::asio::ip::basic_resolver_query<boost::asio::ip::tcp> const&, boost::system::error_code&) (resolver_service.hpp:69)
==18714==    by 0x12989F: boost::asio::ip::resolver_service<boost::asio::ip::tcp>::resolve(std::shared_ptr<void>&, boost::asio::ip::basic_resolver_query<boost::asio::ip::tcp> const&, boost::system::error_code&) (resolver_service.hpp:113)
==18714==    by 0x126A8B: boost::asio::ip::basic_resolver<boost::asio::ip::tcp, boost::asio::ip::resolver_service<boost::asio::ip::tcp> >::resolve(boost::asio::ip::basic_resolver_query<boost::asio::ip::tcp> const&) (basic_resolver.hpp:102)
==18714==    by 0x12290D: TCPTransport::connect() (communication.h:99)
==18714==    by 0x137E3D: Interface::start_transmission() (pf_interface.cpp:94)
==18714==    by 0x117843: main (main.cpp:36)
--18714-- Discarding syms at 0x112cb350-0x112d1d7f in /lib/x86_64-linux-gnu/libnss_files-2.27.so due to munmap()

这是否意味着在我调用connectio_service 对象已不存在?我不明白,因为我使用的是shared_ptrtransport.h 完全一样,只是我从另一个类调用 connect 而不是 main.cpp。

编辑1:我在Transport的构造函数中添加了以下行。

 io_service_thread_ = boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));

但我得到了同样的错误!

【问题讨论】:

    标签: c++11 boost tcp boost-asio


    【解决方案1】:

    您需要使用io_service.run() 运行io_context/io_service 循环。它启动 IO 循环以在 main() 运行期间保持对象处于活动状态。

    您可以在 main 中创建 io_service 实例并在 Transport 等其他类周围传递对它的引用,它们可以维护对 io_service 对象的引用。 一旦你的通信对象都设置好了,你可以在main()中调用io_service.run()

    否则,您也可以使用 Transport 类来运行服务循环。

    【讨论】:

    • 但是在上述情况下,它是如何工作的呢?只要 TCPTransport 的 shared_ptr 在范围内,我希望 io_service 还活着。
    • 取决于您设计类层次结构的方式。您可以在 main 中创建一个 io_service 实例,并将指向它的引用/指针传递给其他类,例如 Transport
    • 我在Transport的构造函数中添加了run()(如编辑1所示),但结果相同。
    • 很奇怪,但是包含标题的顺序导致了问题!以前从未见过!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    相关资源
    最近更新 更多