【发布时间】: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()
这是否意味着在我调用connect 时io_service 对象已不存在?我不明白,因为我使用的是shared_ptr。 transport.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