简体   繁体   中英

ASIO write operation throws std::bad_alloc : C++

I am referring to Chat Client

My write Operation is:

void CSession::beginWrite(const Buffer & message)
{
    //Check if the socket is open or not?
    bool writeInProgress = !writeQueue_.empty();
    writeQueue_.push_back(message);
    if (!writeInProgress) //Exception Thrown here
    {
        asio::async_write(socket_, asio::buffer(writeQueue_.front().received_, writeQueue_.front().buffsize),
            std::bind(&CSession::handle_write, this,
            std::placeholders::_1, std::placeholders::_2));
    }
}

void CSession::handle_write(const asio::error_code& error /*error*/, size_t bytes_transferred /*bytes_transferred*/)
{
    //std::cout << "CSession::handle_write() Called" << "(" << __FILE__ << " : " << __LINE__ << ")" << std::endl;
    if (!error)
    {
        //std::cout << bytes_transferred << " bytes written to the socket." << std::endl;
        writeQueue_.pop_front();
        if (!writeQueue_.empty())
        {
            asio::async_write(socket_, asio::buffer(writeQueue_.front().received_, writeQueue_.front().buffsize),
                std::bind(&CSession::handle_write, this,
                std::placeholders::_1, std::placeholders::_2));
        }
    }
    else
    {
        std::cout << "Write Error Detected" << std::endl;
        std::cout << error.message() << std::endl;
        state_ = false;
        doClose();
        return;
    }
}

It works fine. Then I tried load testing by making client write message Client 2 to the server continuously for 11 minutes as shown below:

bool flag = false;

void setFlag(const asio::error_code& /*e*/)
{
    flag = true;
}

void Client(std::string IP, std::string port)
{
    CSession Session(IP, port);
    Session.initSession();

    asio::thread t(boost::bind(&asio::io_service::run, &(*CIOService::fetchIOService().getIO())));

    asio::deadline_timer timer(*CIOService::fetchIOService().getIO(), boost::posix_time::seconds(675));
    timer.async_wait(&setFlag);

    while (!flag)
    {
        Session.write("Client 2");
    }

    Session.close();
    t.join();
}



void main()
{
    Client("localhost", "8974");
    system("Pause");
}

After 2-3 minutes of successful write operation, the code throws exception Unhandled exception at 0x75B7C42D in NetworkComponentsClient.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x026DE87C. at line

if (!writeInProgress) //Exception Thrown here { asio::async_write(socket_, asio::buffer(writeQueue_.front().received_, writeQueue_.front().buffsize), std::bind(&CSession::handle_write, this, std::placeholders::_1, std::placeholders::_2)); }

Debug shows:

-       writeQueue_ { size=16777215 }   std::deque<channel::Buffer,std::allocator<channel::Buffer> >
+       [0] {received_=0x052a0ac8 "Client 2" }  channel::Buffer
+       [1] {received_=0x052a0b28 "Client 2" }  channel::Buffer
+       [2] {received_=0x052a0b88 "Client 2" }  channel::Buffer
....
....

I can see size of writeQueue_ { size=16777215 } which is very large and hence std::bad_alloc .

Why such behaviour? I can see the code popping messages from deque as below:

if (!error) { writeQueue_.pop_front(); if (!writeQueue_.empty()) { asio::async_write(socket_, asio::buffer(writeQueue_.front().received_, writeQueue_.front().buffsize), std::bind(&CSession::handle_write, this, std::placeholders::_1, std::placeholders::_2)); } }

So write deque should not have grown so large.

My client is supposed to run for days and should be involved large continuous data write. How do I ensure smooth long write operations?

Your consumer ( CSession ) is far slower than your producer ( Client ). Your producer is doing a denial of service attack by producing messages as fast as it can. This is a good test.

Your consumer should (at least one, ideally all):

  • detect that the work is accumulating and set up a policy when such things happen, like "ignore new", "drop oldest"
  • Limit the consumption lag from happening by setting an active filter on incoming messages
  • Improve the performance of incoming messages handling.

My client is supposed to run for days and should be involved large continuous data write. How do I ensure smooth long write operations?

Then you need a much better code than an example found online.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM