2014-02-20 34 views
1

我在使用boost :: asio庫的服務器程序時遇到問題。帶boost :: asio的分段故障,帶deadline的異步udp服務器

服務器類是非常像一個在升壓ASIO教程"asynchronous udp-server"

該類具有一個公共方法(「sendMessageTo」),其由消息稱爲呈現 - 處理器對象,這裏的段錯誤發生,如果該方法由deadline_timer線程調用。它發生在新的std :: string(msg,len)的調用中,這讓我很困惑。 msg包含它應該包含的內容,len也是。

void Server::sendMessageTo(const char* msg, size_t len, udp::endpoint to) 
{ 
    boost::shared_ptr<std::string> message(new std::string (msg,len)); 
    socket.async_send_to(boost::asio::buffer(*message), to, 
         boost::bind(&Server::handleSend, this, message, 
            boost::asio::placeholders::error, 
            boost::asio::placeholders::bytes_transferred)); 
} 

當方法「sendMessageTo」被稱爲第一次嘗試,一切工作正常:它是在同一個線程後來被稱爲,由服務器類的「handleReceive」方法打開。

我的消息處理器對象是某種狀態機,它保留遠程端點,並且在某些狀態中週期性地想要發送一些udp消息回到端點。因此使用asio :: deadline_timer。 最後期限計時器是使用相同的io_service創建的,udp服務器運行。 當定時器第一次被撤銷時,message_processor對象中的state_handling方法會調用發生分段錯誤的「sendMessageTo」方法。 「sendMessageTo」的所有參數都是有效的幷包含期望值。

我的消息處理器類的構造頭(稱爲事務)

Transaction::Transaction(ClientReference *cli, ServerReference *serv) 
    : timer(*(serv->getIOService()), boost::posix_time::milliseconds(TRANSACTION_THREAD_SLEEP_MILLISEC)), 
     clientEndpoint(serv->getEndpoint()) 

定時器是ASIO :: deadline_timer對象,clientEndpoint是udp的::端點

服務器響應發送該方法事務內部:: runThread()

server->sendMessageTo(&encryptedMsgBuf[0], size, clientEndpoint); 

encryptedMsgBuf是字符數組緩衝器,存儲所述加密的消息,並且它是茶的一部分nsaction - 對象。

在方法交易結束:: runThread()的deadline_timer被稱爲到方法runThread()來激活它,直至達到最終狀態:

if (state != done && state != expired) 
    timer.async_wait(boost::bind(&Transaction::runThread, this)); 

謝謝你的優勢。

+0

什麼'Server :: handleSend()'看起來像? –

+0

也許你應該顯示更多的代碼。一個SSCCE浮現在腦海 – sehe

+0

@Stefan'Server :: handleSend()'只是一個空回調處理程序。@sehe,我工作的一個SSCCE,但同時我發現,什麼可能是主要問題。更新的問題,也許會SSCCE如果需要跟隨。 – mburrows2703

回答

1

我不是100%確定這一點,因爲我不能從本地重現您發佈的錯誤,但我強烈懷疑您的問題是由於消息字符串變量的範圍所致。我過去曾遇到boost::shared_ptr的問題,其中shared_ptr比預期早被破壞。如果是這種情況,那麼shared_ptr message可能會在Server::sendMessageTo()的調用結束時被破壞,並且當異步傳輸實際嘗試啓動時,該內存已被釋放導致段錯誤。

一般來說,我喜歡保留緩衝區,我實際上是從我的服務器和客戶端類的私有成員發送和接收的,以確保它們是靜態範圍的,並且不會在我意外中途消失傳輸或接收。它在內存佔用上可能會花費一點點,但我發現它給了我很多的安心。如果這種方法不能給您帶來任何喜悅,請告訴我,我會看看我是否可以在本地重現錯誤。(此刻,我的'本地再現'嘗試包括我用一箇舊的「服務器 - 客戶端使用ASIO」的例子來分配TX緩衝區,如上面所指出的那樣,如果TX試圖做更多的事情堆訪問它應該段錯誤

+0

你好,謝謝你的回答,因爲它是隻是爲了一個個人程序,我把它擱置了一段時間,問題不是,你的建議是什麼,因爲這個消息仍然有效,我得到了segfault錯誤,當我試圖訪問t他在異步調用'Transaction :: runThread'時引用端點,儘管我用copy-constructor創建了它。 – mburrows2703