使用FlatBuffers序列化对象向量出现数据异常的原因
问题原因及解决方案
这个问题的核心是你混淆了FlatBuffers中struct值类型和table引用类型的内存处理逻辑,以及CreatePlumbusesTableDirect函数对struct数组参数的要求。
为什么会出现垃圾值?
FlatBuffers里的struct是内联存储的轻量类型——序列化时会直接把struct的所有字段值复制到FlatBuffer缓冲区中,不需要额外的偏移或引用。而生成的CreatePlumbusesTableDirect函数,针对你的Schema里的plumbuses:[Plumbus](struct数组)参数,实际期望的是const std::vector<Plumbus>*类型(即struct值的集合),但你传入的是const std::vector<const Plumbus*>*(struct指针的集合)。
当FlatBuffers接收到指针数组时,会错误地把这些指针的内存地址值当成struct的二进制数据来解析,自然就输出了毫无意义的垃圾值。
修复代码的正确姿势
你不需要创建指针数组pbPtrs,直接传入原始的std::vector<Plumbus>即可。以下是完整的示例代码:
序列化部分
#include "plumbus_generated.h" #include <flatbuffers/flatbuffers.h> #include <vector> #include <iostream> using namespace rpc; int main() { // 构造Plumbus值的向量 std::vector<Plumbus> pbs; pbs.emplace_back(Plumbus{1, 2.0}); pbs.emplace_back(Plumbus{3, 4.0}); flatbuffers::FlatBufferBuilder builder; // 直接传入Plumbus值的vector指针 auto plumbuses_table = CreatePlumbusesTableDirect(builder, &pbs); builder.Finish(plumbuses_table); // 保存或发送缓冲区...
解析部分
// 解析缓冲区(这里直接用当前builder的缓冲区做测试) const auto root = GetPlumbusesTable(builder.GetBufferPointer()); const auto plumbuses = root->plumbuses(); for (size_t i = 0; i < plumbuses->size(); ++i) { const auto& pb = plumbuses->Get(i); std::cout << "dinglebopBatch = " << pb.dinglebopBatch << ", fleeb = " << pb.fleeb << std::endl; } return 0; }
额外补充:struct vs table的区别
- struct:值类型,无虚表、无偏移,所有字段直接内联在父结构中,适合小的、不变的数据结构。序列化时传递值集合即可。
- table:引用类型,有偏移量,序列化时需要先创建每个table的偏移,再传递指针集合(这也是你误以为可以传指针数组的原因,但struct不适用这个逻辑)。
内容的提问来源于stack exchange,提问作者nnnmmm




