I am finding it a bit silly to ask, to because the minimal example I am posting here works, but when I implement it as part of my project, I get a segfault
. But I will still go ahead and ask.
Below is my code
#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;
}
Before I create a TCP socket, I need to request for a TCP handle. Once done, I can start reading from the device. The code attached above works well. But in case of my actual code, valgrind
complains with:
==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()
Does this mean that io_service
object doesn't exist anymore by the time I call connect
? I don't get it, because I am using a shared_ptr
. The transport.h
is exactly the same, just that instead of main.cpp, I call connect
from another class.
Edit 1: I added the following line in constructor of Transport
.
io_service_thread_ = boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
But I get the same error!
Aucun commentaire:
Enregistrer un commentaire