chriskohlhoff / asio

Asio C++ Library
http://think-async.com/Asio
4.85k stars 1.2k forks source link

Hi there, i have a big issues about maximum of sizeof buffer in boost::bind handler function. It makes my program crash and i don't know why and i can't chase #630

Open ghost opened 3 years ago

ghost commented 3 years ago

@andrewnguyen94 commented on Jul 24, 2018, 10:25 AM UTC:

Here is my tcp socket client `class chat_client { public: chat_client(boost::asio::io_service& io_service, tcp::resolver::iterator endpoint_iterator) : ioservice(ioservice), socket(io_service), t(io_service) { boost::asio::asyncconnect(socket, endpoint_iterator, boost::bind(&chat_client::handle_connect, this, boost::asio::placeholders::error)); } 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)); // ioservice.post(boost::bind(&chat_client::do_write, this, msg)); ioservice.run(); } void do_write(chat_message msg, const boost::system::error_code& error) { std::cout << "dcm" << std::endl; bool write_in_progress = !writemsgs.empty(); writemsgs.push_back(msg); if (!write_in_progress) { boost::asio::asyncwrite(socket, boost::asio::buffer(writemsgs.front().data(), writemsgs.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) { writemsgs.pop_front(); if (!writemsgs.empty()) { boost::asio::asyncwrite(socket, boost::asio::buffer(writemsgs.front().data(), writemsgs.front().length()), boost::bind(&chat_client::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } } else { do_close(); } }

void doclose() { socket.close(); }

private: boost::asio::io_service& ioservice; tcp::socket socket_; chat_message readmsg; chat_message_queue writemsgs; int engineId; bool flag = false; bool flag_engine = false; response res; boost::asio::deadline_timer t; };`

---- I generate a function which can push the image to server using write function. request is parsed to chat_message class. Here is my chat_message class

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

chat_message() : bodylength(0) { }

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

char* data() { return data_; }

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

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

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

size_t body_length() const { return bodylength; }

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

bool decode_header() { using namespace std; // For strncat and atoi. char header[headerlength + 1] = ""; strncat(header, data, header_length); bodylength = atoi(header); if (bodylength > max_body_length) { bodylength = 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(bodylength)); memcpy(data_, header, header_length); }

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

when i set max_body_length >= 655365, it's crashed with segmentation faults at write() function. I doubt that, boost::bind() function have a maximum buffer, but i can't find any informations about that. Can someone help me, thank you guys.

This issue was moved by chriskohlhoff from boostorg/asio#132.

ghost commented 3 years ago

@uecasm commented on Aug 22, 2018, 2:05 AM UTC:

You should ask support questions on the mailing list or on StackOverflow, not here. Issues are for actual verifiable bug reports.

Having said that, your problem is that chat_message includes an array directly in its body, and do_write accepts that by value, meaning that it's going to be copied around on the stack. You're probably overflowing the stack as a result. Use the heap for large memory blocks instead, and avoid unnecessary copies.

Another possible problem is that if chat_message_queue might invalidate previous elements on a push_back operation (eg. as vector does) then a concurrent write might crash a previous write operation by deallocating the message out from under it.