2015-02-23 75 views
0

我指的是Chat ClientASIO寫操作拋出的std :: bad_alloc的:C++

我的寫操作是:

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; 
    } 
} 

它工作正常。然後,我通過使客戶端的寫消息Client 2連續11分鐘的服務器試圖負載測試,如下所示:

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"); 
} 

2-3分鐘後成功寫操作的,該代碼在線拋出異常Unhandled exception at 0x75B7C42D in NetworkComponentsClient.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x026DE87C.

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)); }

調試表明:

-  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 
.... 
.... 

我可以看到大小這是非常大的,因此std::bad_alloc

爲什麼會這樣的行爲?我可以看到代碼從雙端隊列彈出消息如下:

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)); } }

所以write deque不應該過於龐大。

我的客戶應該運行幾天,應該涉及大量連續數據寫入。如何確保順利的長時間寫入操作?

+0

您在緊密的循環中儘可能快地對消息排隊,但網絡堆棧將無法快速運行,因此隊列不斷增長並增長。我們不知道你的'Buffer'類是如何構造的,但大概每個實例都使用了一些內存,這些內存都加起來了。如果您想將其作爲真實世界的測試,您需要添加一些速率限制。 – 2015-02-23 10:16:00

+0

@JonathanPotter緩衝區是字符數組 - \t'結構緩衝 \t { \t \t枚舉{BUFFSIZE = 32}; \t \t char received_ [buffsize]; \t \t緩衝液(){} \t \t緩衝液(標準::字符串str) \t \t { \t \t \t //截斷如果溢出 \t \t \t自動LEN = str.size(); \t \t \t如果(LEN> = BUFFSIZE) \t \t \t { \t \t \t \t LEN = BUFFSIZE - 1; \t \t \t} \t \t \t的std ::拷貝(str.begin(),str.begin()+ LEN,received_); \t \t \t received_ [str.size()] ='\ 0'; \t \t} \t};'我想這是我能做的最簡單的緩衝區。你有更好的緩衝區結構的想法,以獲得更好的性能嗎? – 2015-02-23 10:19:30

回答

0

您的消費者(CSession)遠遠落後於您的生產商(Client)。 您的製作人正在通過儘可能快地生成郵件來進行拒絕服務攻擊。這是一個很好的測試。

你的消費者應(至少一個,最好是全部):

  • 檢測工作正在積累,併成立了政策時,這樣的事情發生,就像「忽略新」,「降最古老的」
  • 通過在傳入消息上設置有效過濾器來限制發生的消耗滯後
  • 改善傳入消息處理的性能。

我的客戶應該是幾天運行,並可參與大 連續數據寫入。如何確保順利的長時間寫入操作?

然後你需要比在線找到的例子好得多的代碼。

相關問題