Search code examples
c++boost-asio

Where/when is the buffer deleted in boost::asio::async_write(..) for the code provided


The code below works and works well for millions of messages on a daily basis. My question how/where does "msg" that is set up as a const vector get deleted if in fact that is what's happening? I do not do anything in the completion handler to remove it. Thanks

The typedef is set in the tcp_connection class. The method is also part of the class.

int tcp_connection::writeToSocketAsync(std::string sMsg)
{
    typedef boost::shared_ptr<CharVec>  CharVecPtr;

    const std::vector<char> msg(sMsg.begin(), sMsg.end());
    
    CharVecPtr tmsg = boost::make_shared<CharVec>(msg);

    boost::asio::async_write(socket_,
        boost::asio::buffer(*tmsg),
        boost::asio::transfer_all(),
        strand_.wrap(boost::bind(&tcp_connection::handle_write,
            this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred)));
}

Solution

  • The answer is: it doesn't get destroyed in async_write, because the caller owns it.

    The code as written invokes Undefined Behaviour. The buffer must be kept alive until the operation completes: doc

    buffers

    One or more buffers containing the data to be written. Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the completion handler is called.

    A typical solution works like this:

    #include <boost/asio.hpp>
    #include <iostream>
    using namespace std::placeholders;
    namespace asio = boost::asio;
    using asio::ip::tcp;
    
    struct tcp_connection {
        tcp_connection(tcp::socket s) : socket_(std::move(s)) {}
    
        void connect(std::string const& host, std::string const& port) {
            tcp::resolver resolver(socket_.get_executor());
            asio::connect(socket_, resolver.resolve(host, port));
        }
    
        void writeToSocketAsync(std::string sMsg)
        {
            outgoing_message_ = std::move(sMsg);
    
            asio::async_write(                                    //
                socket_,                                          //
                asio::buffer(outgoing_message_),                  //
                bind(&tcp_connection::handle_write, this, _1, _2) //
            );
        }
    
        void handle_write(boost::system::error_code const& ec, size_t n) {
            std::cout << "Sent " << n << " bytes (" << ec.message() << ")" << std::endl;
        }
    
      private:
        tcp::socket socket_;
        std::string outgoing_message_;
    };