簡體   English   中英

Boost.Asio:發送太大消息時出現分段錯誤

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

我的程序將一些內部日志保存到.txt文件。 如果通過TCP(SSL加密)連接到該服務器,則程序將發送日志文件的內容。

這是發送數據的代碼:

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

所以NIUserSession::write被作為字符串傳遞日志文件的內容。

如果程序長時間沒有運行,則日志文件會很短,並且一切正常。 但是,如果運行了一段時間並且日志文件越來越長,則該程序在嘗試發送數據時將收到SIGSEGV 這是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

我不明白為什么會這樣。 我是否可能需要增大boost::asio::buffer的大小?

另外, io_service::run()在其自己的分離線程中運行。 這可能是個問題嗎?

這是asio使用的常見問題。 您正在使用boost::asio::buffer(message)發送緩沖區,該boost::asio::buffer(message)不會復制數據。 它只是為數據創建引用,您將負責此對象(您的message )的生命周期,直到操作結束。 但是當您退出函數NIUserSession::write所有堆棧變量都將被破壞,包括您的message

要解決此問題,您應該將數據放入壽命更長的對象中,例如,放在shared_ptr中 有效的示例可以是這樣的:

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