We have a template class which owns some std::unique_ptr, some of which are boost::asio
template <class cloud_type,
bool keep_alive = true,
class socket_type = asio_http,
class error_handle = default_error_handler>
class callable
{
callable() = delete;
// other stuff here, click the link to see actual code
};
It has two constructors and we've made a wrapper function which supposedly simplifies things:
template <class cloud_type,
bool keep_alive = true,
class socket_type = asio_http,
class error_handle = default_error_handler,
class ...args,
typename =
typename std::enable_if<!std::is_same<cloud_type,
cloud_batch>::value, bool>>
callable<cloud_type,keep_alive,socket_type,error_handle>
call(typename cloud_type::callback functor,
args... params)
{
return callable<cloud_type,
keep_alive,
socket_type,
error_handle>(functor, default_node, params...);
}
Two of us have tested this, on Ubuntu 16.04 with G++ 5.9 and Boost 1.58. When we build a Release version (with -O3) the application works fine. When however we build a Debug version, the application SEGFAULTs. The actual error I get is:
Thread 1 "human_detection" received signal SIGSEGV, Segmentation fault.
0x0000000000443128 in std::unique_ptr<boost::asio::io_service, std::default_delete<boost::asio::io_service> >::get (this=0x120) at /usr/include/c++/5/bits/unique_ptr.h:305
305 { return std::get<0>(_M_t); }
This seems to originate from:
#0 0x0000000000443128 in std::unique_ptr<boost::asio::io_service, std::default_delete<boost::asio::io_service> >::get (this=0x120) at /usr/include/c++/5/bits/unique_ptr.h:305
#1 0x0000000000441880 in std::unique_ptr<boost::asio::io_service, std::default_delete<boost::asio::io_service> >::operator-> (this=0x120) at /usr/include/c++/5/bits/unique_ptr.h:298
#2 0x000000000043f2b4 in noos::cloud::callable<noos::cloud::human_detection, false, noos::cloud::asio_http, noos::cloud::default_error_handler>::send (this=0x0, timeout=0) at /home/zuperath/code/noos-api-maria/./noos/cloud/callable.tpl:120
Which points to:
void callable<cloud_type,
keep_alive,
socket_type,
error_handle
>::send(unsigned int timeout)
{
assert(socket_ && query_ && resol_ && io_);
if (!socket_)
throw std::runtime_error("socket not set");
if (!io_ || !query_ || !resol_)
throw std::runtime_error("io, query or resolver not set");
object.fill_buffer(boost::ref(*buffer_.get()), endpoint);
socket_->is_connected() ?
socket_->send(*query_.get(), *resol_.get(), timeout, *buffer_.get()) :
socket_->begin(*query_.get(), *resol_.get(), timeout);
io_->run();
io_->reset(); // here !!!
}
I'm trying to understand what we're doing wrong, and I'm guessing that Release uses RVO, whereas Debug makes a copy which results in the above?
When I call the wrapper:
auto query = call<human_detection,false>(
[&](std::vector<noos::object::human> humans) {
std::cout << "Found " << humans.size() << " humans!" << std::endl;
}, pic);
The error persists during Debug whereas if I call the class constructor directly, the SEGFAULT goes away:
callable<human_detection,false> query([&](std::vector<noos::object::human> humans) {
std::cout << "Found " << humans.size() << " humans!" << std::endl;
}, default_node, pic);
My fear is that there is an underlying problem with the resources of the class (e.g., boost::asio::io) which is enabled by making the class copyable.
Aucun commentaire:
Enregistrer un commentaire