-1

i have a question about maximum size of buffer in handler function which is called in boost::bind method. I have a tcp socket client:

chat_client(boost::asio::io_service& io_service,
  tcp::resolver::iterator endpoint_iterator)
: io_service_(io_service),
  socket_(io_service),
  t(io_service)
{
    boost::asio::async_connect(socket_, endpoint_iterator,
           boost::bind(&chat_client::handle_connect, this,
           boost::asio::placeholders::error));
}

in chat_client class, i create a method to write request to socket buffer

 void set_timer(boost::posix_time::ptime time, boost::function<void(const 
      boost::system::error_code&)> handler)
 {
     t.expires_at(time);
     t.async_wait(handler);
 }
void write(const chat_message& msg)
{
     set_timer(boost::posix_time::microsec_clock::universal_time() + 
          boost::posix_time::seconds(1),
          boost::bind(&chat_client::do_write, this, msg, 
          boost::asio::placeholders::error));
     io_service_.run();
}
void do_write(chat_message msg, const boost::system::error_code& error)
{
     std::cout << "dcm" << std::endl;
     bool write_in_progress = !write_msgs_.empty();
     write_msgs_.push_back(msg);
     if (!write_in_progress)
     {
          boost::asio::async_write(socket_,
                            boost::asio::buffer(write_msgs_.front().data(),
                            write_msgs_.front().length()),
                            boost::bind(&chat_client::handle_write, this,
                            boost::asio::placeholders::error,
                            boost::asio::placeholders::bytes_transferred));
     }
}

void handle_write(const boost::system::error_code& error, size_t 
      bytes_transferred)
{
    if (!error)
    {
         write_msgs_.pop_front();
         if (!write_msgs_.empty())
         {
              boost::asio::async_write(socket_,
                             boost::asio::buffer(write_msgs_.front().data(),
                             write_msgs_.front().length()),
                             boost::bind(&chat_client::handle_write, this,
                             boost::asio::placeholders::error,
                             boost::asio::placeholders::bytes_transferred));
         }
    }
    else
    {
         do_close();
    }
}

My request content is packaged in an instance of chat_message class. And here is chat_message class:

class chat_message
{
public:
    enum { header_length = 7 };
    enum { max_body_length = 0x1FFFFF };

    chat_message()
    : body_length_(0)
    {
    }

    const char* data() const
    {
        return data_;
    }

    char* data()
    {
        return data_;
    }

    size_t length() const
    {
        return header_length + body_length_;
    }

    const char* body() const
    {
        return data_ + header_length;
    }

    char* body()
    {
        return data_ + header_length;
    }

    size_t body_length() const
    {
        return body_length_;
    }

    void body_length(size_t new_length)
    {
        body_length_ = new_length;
        if (body_length_ > max_body_length)
            body_length_ = max_body_length;
    }

    bool decode_header()
    {
        using namespace std; // For strncat and atoi.
        char header[header_length + 1] = "";
        strncat(header, data_, header_length);
        body_length_ = atoi(header);
        if (body_length_ > max_body_length)
        {
            body_length_ = 0;
            return false;
        }
        return true;
    }

    void encode_header()
    {
        using namespace std; // For sprintf and memcpy.
        char header[header_length + 1] = "";
        sprintf(header, "%4d", static_cast<int>(body_length_));
        memcpy(data_, header, header_length);
    }

private:
    char data_[header_length + max_body_length];
    size_t body_length_;
};

My issue is when i set max_body_length > 0xFFFFF, boost::bind() method in write() function lead to segmentation fault. So i doubt that, boost::bind() method has a maximum of buffersize. Can someone explain it for me? Thank you

1 Answers1

0

The problem is not in boost::bind() but in the following:

char data_[header_length + max_body_length];

This line will compile alright but can crash when elements get accessed. I would strongly recommend not to use such a huge array of chars here. As one of the ways to keep it you might think about dynamic allocation. Or move from array at all. STL and BOOST libraries provide a lot of tools to safely handle strings and collections.

StahlRat
  • 1,199
  • 13
  • 25
  • yeah. Actually, in my program, i want to transfer image data from client to server. Hence, i set max_body_length > 0xFFFFF. Would you mind to suggest for me an efficence way to transfer a huge of char using STL or BOOST – nguyen andrew Jul 24 '18 at 17:30
  • It's a chat application, right? :) Does your design really allow people to send something > 0xFFFFF which is about size of 1MByte ? Anyway, my answer to your second question will be to have something like `std::vector data_;` instead of `char data_[];` – StahlRat Jul 24 '18 at 17:50
  • okay, i will try. If it's about method of allocation, it will be alright. But if it's not, i think the app will crash. Anyway, thank you. I will post the result after i editted the code and tested it – nguyen andrew Jul 24 '18 at 18:00
  • thank you for your help. I editted and tested successfull. It's all about the bad allocation from me. It's work perfectly – nguyen andrew Jul 25 '18 at 03:58