简体   繁体   English

使用boost :: asio的分段错误,带有截止时间的异步udp服务器

[英]Segmentation fault with boost::asio, asynchronous udp-server with deadline_timer

I am having trouble with a server program using the boost::asio library. 我在使用boost :: asio库的服务器程序时遇到了麻烦。

The Server class is very much like the one presented in the boost asio tutorial "asynchronous udp-server" Server类非常类似于boost asio教程“异步udp服务器”中介绍的类。

The class has a public method ("sendMessageTo"), which is called by a message - processor object, here the segmentation fault occurs, if the method is invoked by the deadline_timer thread. 该类具有一个公共方法(“ sendMessageTo”),该公共方法由消息-处理器对象调用,如果该方法由Duration_timer线程调用,则会发生分段错误。 It occurs with the call of new std::string(msg, len), this is puzzeling me. 它通过调用新的std :: string(msg,len)发生,这让我感到困惑。 msg contains what it should contain, and len too. 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));
}

When the method "sendMessageTo" is called on the first attempt, everything works fine: It is called later in the same thread, that is opened by the "handleReceive" method of the server class. 第一次尝试调用方法“ sendMessageTo”时,一切正常:稍后在同一线程中调用,该线程由服务器类的“ handleReceive”方法打开。

My message-processor object is some kind of state-machine, that keeps the remote-endpoint, and in some states periodically wants to send some udp Messages back to the endpoint. 我的消息处理器对象是某种状态机,它保留远程端点,并且在某些状态下定期希望将一些udp消息发送回端点。 Therefor a asio::deadline_timer is used. 因此,使用了一个asio :: deadline_timer。 The deadline timer is created with the same io_service, the udp-server runs on. 截止时间计时器是使用相同的io_service创建的,udp服务器在其上运行。 When the timer is revoked for the first time, the state_handling method inside the message_processor object calls the "sendMessageTo" method an segmentation fault occurs. 首次取消计时器时,message_processor对象内的state_handling方法将调用“ sendMessageTo”方法,从而发生分段错误。 All arguments of "sendMessageTo" are valid and contain the expected values. “ sendMessageTo”的所有参数均有效,并包含期望值。

The constructor head of my message-processor class (called Transaction) 我的消息处理器类的构造函数头(称为Transaction)

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

timer is the asio::deadline_timer object, and clientEndpoint is the udp::endpoint timer是asio :: deadline_timer对象,clientEndpoint是udp :: endpoint

the server response is sent inside the method Transaction::runThread() 服务器响应在方法Transaction :: runThread()中发送

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

encryptedMsgBuf is a char array buffer, that stores the encrypted message, and it is part of the Transaction - object. cryptoMsgBuf是一个char数组缓冲区,用于存储加密的消息,并且是Transaction-对象的一部分。

at the end of the method Transaction::runThread() the deadline_timer is called onto the method runThread() to reactivate it until the final state is reached: 在方法Transaction :: runThread()的末尾,将delay_timer调用到方法runThread()上以重新激活它,直到达到最终状态:

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

Thank you in advantage. 谢谢你的帮助。

I'm not 100% sure on this one, since I can't locally reproduce your error from what you've posted, but I strongly suspect your problem is due to the scoping of the message string variable. 我不确定这件事是100%肯定的,因为我无法从您发布的内容中本地重现您的错误,但是我强烈怀疑您的问题是由于消息字符串变量的作用域所致。 I have had some issues with boost::shared_ptr in the past, where the shared_ptr has been destructed earlier than expected. 我过去在boost::shared_ptr遇到过一些问题,其中shared_ptr破坏早于预期。 If this is the case, then shared_ptr message may be getting destructed at the end of the call to Server::sendMessageTo() , and when the asynchronous tranmission actually attempts to start, that memory has been deallocated causing a segfault. 如果是这种情况,则在对Server::sendMessageTo()的调用结束时, shared_ptr message可能会被破坏,并且当异步传输实际上尝试开始时,该内存已被释放,从而导致段错误。

In general, I like to keep the buffers which I am actually transmitting from and receiving to as private members of my server and client classes to ensure they are statically scoped and won't vanish on me unexpectedly half-way through a transmit or receive. 总的来说,我希望将实际上从我接收和接收到的缓冲区作为服务器和客户端类的私有成员,以确保它们是静态范围的,并且不会在发送或接收过程中途意外消失。 It can cost a bit in memory footprint, but I find it gives me a lot of peace-of-mind. 它可能会占用一些内存,但是我发现它让我省心了。 If this approach doesn't give you any joy, let me know and I'll see if I can reproduce the error locally. 如果这种方法不能给您带来任何快乐,请告诉我,我将看看是否可以在本地重现该错误。 (At the moment my 'local reproduction' attempts have consisted of me hacking an old "server-client using ASIO" example to allocate the TX buffer as you've indicated above, then thrash some memory so if the TX is trying to do further heap access it should segfault. (目前,我的“本地复制”尝试包括我破解了一个旧的“使用ASIO的服务器-客户端”示例以如上所述分配分配TX缓冲区,然后浪费了一些内存,因此如果TX试图做进一步的工作堆访问它应该是段错误的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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