c++ lambda self-passing exception -
when run code, std::bad_functon_call exception. cannot figure out whats reason exception. it's thrown async_receive inside receivecallback. receivecallback cleared out memory before being called?
//callback on connection accepted std::function<void(const boost::system::error_code& error, tcp::socket* socketptr)> acceptcallback = [this, onmessagereceivedcallback, acceptcallback](const boost::system::error_code& error, tcp::socket* socketptr) { cout<<"accept: "<<error.message()<<endl; const int buffersize = 100; char* message = new char[buffersize]; //callback on message received std::function<void(const boost::system::error_code& error,std::size_t bytes_transferred)> receivecallback = [message, buffersize, socketptr, onmessagereceivedcallback, receivecallback](const boost::system::error_code& error,std::size_t bytes_transferred) { onmessagereceivedcallback(message, bytes_transferred); socketptr->async_receive( boost::asio::buffer(message, buffersize), receivecallback); }; socketptr->async_receive( boost::asio::buffer(message, buffersize), receivecallback); //create socket next connection socketptr = new tcp::socket(io_service_); //continue accepting connections acceptor_.async_accept(*socketptr, std::bind(acceptcallback, std::placeholders::_1, socketptr));
your code undefined behaviour: when lambda captures receivecallback
value, receivecallback
not yet initialized copy lambda gets garbage (with gcc 4.7 segfault instead of std::bad_function_call
). acceptcallback
exhibits same problem way.
an apparent solution capture receivecallback
reference instead of value, pose problems related lifetime of object (the receivecallback
object must stay alive whole duration of i/o operations, gets destroyed exit accept
lambda).
it's chicken , egg situation: capture reference won't work because of lifetime issues, need capture value solve that, capture value makes copy of uninitialized object need capture reference solve that. meh.
note receivecallback
incorrect in way: capture message
value too, means whenever lambda called you'll end not buffer filled boost::asio
, copy of buffer made when lambda instantiated (in other words, uninitialized garbage again).
now diagnostic made, how fix , write working code?
in opinion, drop lambdas altogether. write class hold message
buffer , onmessagereceivedcallback
, , has accept
, receive
member functions.
depending on exact api of boost::asio
may need "wrap" member functions in std::function
objects callbacks asio
can use (std::mem_fn
friend here, don't forget std::bind
first argument of resulting std::function
object instance of class).
Comments
Post a Comment