【问题标题】:Flatbuffers causing Segmentation fault when sent over TCP with Boost ASIO使用 Boost ASIO 通过 TCP 发送时,Flatbuffers 会导致分段错误
【发布时间】:2020-09-22 11:32:17
【问题描述】:

我正在使用FlatBuffers & Boost ASIO

这是我如何形成我的消息并将其从客户端发送到服务器:

size_t const header_length = 8;
size_t const body_size_b = 8;
std::string data;


ServerOpcode opc;
opc = ServerOpcode::SMSG_LOGIN_REQUEST_RESPONSE_TEST;

flatbuffers::FlatBufferBuilder builder;
auto name = builder.CreateString("Orc Monster");
auto accountRole = Vibranium::CreateAccountRole_Packet(builder,1,name);


std::ostringstream header_stream;
header_stream << std::setw(header_length) << std::hex << opc;

std::ostringstream body_size_stream;
body_size_stream << std::setw(body_size_b) << std::hex << builder.GetSize();

data += header_stream.str();
data += body_size_stream.str();
boost::asio::streambuf b;
std::ostream os(&b);

size_t request_length = data.length();

boost::asio::write(s, boost::asio::buffer(data,request_length));
boost::asio::write(s, boost::asio::buffer(&accountRole,builder.GetSize()));

这是我在服务器端的阅读方式:

void Vibranium::Client::read_header() {
    auto self(shared_from_this());
    _packet.header_.resize(Packet::header_size_in_bytes);
    boost::asio::async_read(socket,
    boost::asio::buffer(_packet.header_, Packet::header_size_in_bytes),
    [this, self](boost::system::error_code ec, std::size_t /*length*/)
    {
        if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec))
        {
            Disconnect();
        }
        else
        {
            std::ostringstream header_stream;
            header_stream << std::setw(Packet::header_size_in_bytes) << std::hex << _packet.header_;
            std::cout << "Header: " << std::endl;
            std::cout << std::hex << header_stream.str() << std::endl;
            read_body_size();
        }
    });
}
void Vibranium::Client::read_body_size() {
    auto self(shared_from_this());
    _packet.body_size_.resize(Packet::body_size_in_bytes);
    socket.async_read_some(boost::asio::buffer(_packet.body_size_, Packet::body_size_in_bytes),
   [this, self](boost::system::error_code ec, std::size_t length)
   {
       if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec))
       {
           Disconnect();
       }
       else
       {
           std::cout << "Body Size: " << std::endl;
           std::cout << _packet.body_size_ << std::endl;
           std::stringstream ss;
           ss << std::hex << _packet.body_size_;
           ss >> _packet.body_in_bytes;
           read_body();
       }
   });
}

void Vibranium::Client::read_body() {
    auto self(shared_from_this());
    _packet.body_.resize(_packet.body_in_bytes);
    socket.async_read_some(boost::asio::buffer(_packet.body_, _packet.body_in_bytes),
   [this, self](boost::system::error_code ec, std::size_t length)
   {
       if ((boost::asio::error::eof == ec) || (boost::asio::error::connection_reset == ec))
       {
           Disconnect();
       }
       else
       {
           try
           {
               auto ac = GetAccountRole_Packet(&_packet.body_);
               std::cout << ac->name()->str() << std::endl;
           }
           catch (std::exception& e)
           {
               std::cout << "Error bace!" << std::endl;
               // Unable to decode data.
               boost::system::error_code error(boost::asio::error::invalid_argument);
               return;
           }

           std::cout << "Body: " << std::endl;
           std::cout << _packet.body_ << std::endl;
           //Send(ServerOpcode::SMSG_AUTH_CONNECTION_RESPONSE,"How are you, mate?");
           read_header();
       }
   });
}


void Vibranium::Client::Disconnect() const {
    Logger::Log("Disconnected ID: " + std::__cxx11::to_string(this->connectionId), Logger::Error, true);
    for (int i = 0; i < Vibranium::Server::Clients.size(); ++i) {
        if(Vibranium::Server::Clients[i]->connectionId == this->connectionId)
            Vibranium::Server::Clients.erase(Vibranium::Server::Clients.begin() + i);
    }
}

当服务器端收到消息时,我得到以下输出:

Header: 
     a99
Body Size: 
      24
Segmentation fault (core dumped)

然后,如果我尝试使用 gdb 查看有关 seg 故障的更多详细信息,我会看到以下输出:

Core was generated by `./AuthServer'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f0ad833c202 in flatbuffers::ReadScalar<int> (p=0x30bd6e0) at /usr/local/include/flatbuffers/base.h:392
392   return EndianScalar(*reinterpret_cast<const T *>(p));

为什么服务器崩溃了?我做错了什么,我该如何解决?

附: 我很确定这条线 std::cout &lt;&lt; ac-&gt;name()-&gt;str() &lt;&lt; std::endl; 会导致崩溃,但我不明白为什么。

【问题讨论】:

    标签: c++ boost-asio flatbuffers


    【解决方案1】:

    就像我在您针对此主题提出的其他许多问题之一中所说的那样,您首先需要阅读有关 FlatBuffers 的教程: https://google.github.io/flatbuffers/flatbuffers_guide_tutorial.html

    一些提示:

    • 您没有完成缓冲区。
    • 您实际上并没有在编写代码的任何地方使用缓冲区,只是获取它的大小。
    • 您似乎在读/写时随意混合二进制和字符串。 FlatBuffers 只需要写成二进制。 std::hex 之类的东西用于文本输出。

    提示:在不了解它们的情况下将它们放在一起可能会起作用,例如Python,但它会导致 C++ 崩溃。您需要实际学习语言和 API 以及它们的工作原理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多