简体   繁体   English

Boost.Asio:发送太大消息时出现分段错误

[英]Boost.Asio: Segmentation fault when sending too big message

My program saves some internal logs to a .txt file. 我的程序将一些内部日志保存到.txt文件。 If you connect to it via TCP (SSL encrypted), the program will send the contents of the log file. 如果通过TCP(SSL加密)连接到该服务器,则程序将发送日志文件的内容。

This is the code that is sending the data: 这是发送数据的代码:

void NIUserSession::write(std::string message)
{
    std::cout << "Writing message" << std::endl;
    message.append("<EOF>");
    boost::system::error_code ec;
    boost::asio::async_write(this->socket_, boost::asio::buffer(message),
                       boost::asio::transfer_all(), boost::bind(&NIUserSession::writeHandler,
                                                                this, boost::asio::placeholders::error,
                                                                boost::asio::placeholders::bytes_transferred()));
}

void NIUserSession::writeHandler(const boost::system::error_code &error, std::size_t bytes_transferred)
{
    std::cout << "Write Handler" << std::endl;
    if(error)
    {
        std::cout << "Write handler error: " << error.message() << std::endl;
        this->disconnect();
    }
}

So NIUserSession::write gets passed the logfile contents as string. 所以NIUserSession::write被作为字符串传递日志文件的内容。

If the program is not running for a very long time the logfile is short and everything works fine. 如果程序长时间没有运行,则日志文件会很短,并且一切正常。 However, if it runs for a while and the log file gets longer and longer, the program will receive a SIGSEGV when it tries to send the data. 但是,如果运行了一段时间并且日志文件越来越长,则该程序在尝试发送数据时将收到SIGSEGV This is the gdb log: 这是gdb日志:

Writing message

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff4fe1700 (LWP 21047)]
__memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:33
33      ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S: No such file or directory.
(gdb) where
#0  __memcpy_sse2_unaligned () at ../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:33
#1  0x00007ffff7998454 in ?? () from /lib/x86_64-linux-gnu/libssl.so.1.0.0
#2  0x00007ffff79985c3 in ?? () from /lib/x86_64-linux-gnu/libssl.so.1.0.0
#3  0x00000000004b7eca in boost::asio::ssl::detail::io_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, boost::asio::ssl::detail::write_op<boost::asio::const_buffers_1>, boost::asio::detail::write_op<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::asio::const_buffers_1, boost::asio::detail::transfer_all_t, boost::_bi::bind_t<void, boost::_mfi::mf2<void, NIUserSession, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<NIUserSession*>, boost::arg<1> (*)(), boost::arg<2> > > > >::operator()(boost::system::error_code, unsigned long, int) ()
#4  0x00000000004b8bf8 in boost::asio::detail::write_op<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::asio::const_buffers_1, boost::asio::detail::transfer_all_t, boost::_bi::bind_t<void, boost::_mfi::mf2<void, NIUserSession, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<NIUserSession*>, boost::arg<1> (*)(), boost::arg<2> > > >::operator()(boost::system::error_code const&, unsigned long, int) ()
#5  0x00000000004b7e6c in boost::asio::ssl::detail::io_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, boost::asio::ssl::detail::write_op<boost::asio::const_buffers_1>, boost::asio::detail::write_op<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::asio::const_buffers_1, boost::asio::detail::transfer_all_t, boost::_bi::bind_t<void, boost::_mfi::mf2<void, NIUserSession, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<NIUserSession*>, boost::arg<1> (*)(), boost::arg<2> > > > >::operator()(boost::system::error_code, unsigned long, int) ()
#6  0x00000000004b965c in boost::asio::detail::reactive_socket_send_op<boost::asio::mutable_buffers_1, boost::asio::detail::write_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, boost::asio::mutable_buffers_1, boost::asio::detail::transfer_all_t, boost::asio::ssl::detail::io_op<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >, boost::asio::ssl::detail::write_op<boost::asio::const_buffers_1>, boost::asio::detail::write_op<boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >, boost::asio::const_buffers_1, boost::asio::detail::transfer_all_t, boost::_bi::bind_t<void, boost::_mfi::mf2<void, NIUserSession, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<NIUserSession*>, boost::arg<1> (*)(), boost::arg<2> > > > > > >::do_complete(boost::asio::detail::task_io_service*, boost::asio::detail::task_io_service_operation*, boost::system::error_code const&, unsigned long) ()
#7  0x00000000004add59 in boost::asio::detail::epoll_reactor::descriptor_state::do_complete(boost::asio::detail::task_io_service*, boost::asio::detail::task_io_service_operation*, boost::system::error_code const&, unsigned long) ()
#8  0x00000000004ad911 in boost::asio::detail::task_io_service::run(boost::system::error_code&) ()
#9  0x00000000004a9c1f in NetInterface::init() ()
#10 0x00007ffff641aa60 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#11 0x00007ffff566e184 in start_thread (arg=0x7ffff4fe1700) at pthread_create.c:312
#12 0x00007ffff5b8237d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

I don't understand why it is happening. 我不明白为什么会这样。 Do I maybe have to give a size to boost::asio::buffer ? 我是否可能需要增大boost::asio::buffer的大小?

Also, io_service::run() is running in its own detached thread. 另外, io_service::run()在其自己的分离线程中运行。 Could this be a problem? 这可能是个问题吗?

This is the common issue with asio usage. 这是asio使用的常见问题。 You are sending buffer using boost::asio::buffer(message) , which does not copy the data. 您正在使用boost::asio::buffer(message)发送缓冲区,该boost::asio::buffer(message)不会复制数据。 It just creating a reference for the data and you are responsible for this object (your message ) lifetime until operation ends. 它只是为数据创建引用,您将负责此对象(您的message )的生命周期,直到操作结束。 But when you exit function NIUserSession::write all stack variables are destroyed, including your message . 但是当您退出函数NIUserSession::write所有堆栈变量都将被破坏,包括您的message

To fix this you should place your data into a object with longer lifetime, for example into shared_ptr . 要解决此问题,您应该将数据放入寿命更长的对象中,例如,放在shared_ptr中 Valid example can be something like this: 有效的示例可以是这样的:

void NIUserSession::write(std::string &message_orig)
{
    std::cout << "Writing message" << std::endl;

    std::shared_ptr message = std::make_shared<std::string>( message_orig );
    message->append("<EOF>");
    boost::system::error_code ec;
    boost::asio::async_write(this->socket_, boost::asio::buffer(*message),
        boost::asio::transfer_all(), boost::bind(&NIUserSession::writeHandler,
               this, boost::asio::placeholders::error,
               boost::asio::placeholders::bytes_transferred(),
               message /* <- capture it into callback to guarantee lifetime */
               ));
}

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

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