Flatbuffer多根表用错误根类型解码未报错,是否符合预期?
FlatBuffer用错误根类型解码未触发失败是否属于预期行为?
这确实是FlatBuffer的预期行为。
原因解析
FlatBuffer的表结构本身没有内置类型标识信息,root()方法的默认验证逻辑仅负责检查缓冲区的格式合法性(比如偏移值是否有效、数据是否符合字段类型的内存布局),不会验证当前解码的类型是否与序列化时的根类型一致。
你的两个表Weapon和Shield前两个字段的内存布局完全兼容:都是string类型的name、short类型的damage,所以用Weapon解码Shield的缓冲区时,内存解析不会触发错误;而Weapon特有的two_handed字段,会被解析为缓冲区内存对应位置的随机值(你的测试输出中为true,实际是未初始化的内存数据)。
另外注意到你构建Shield缓冲区时的代码错误:误用了schema::Weapon::create生成数据,实际产出的还是Weapon结构,但即使你正确生成Shield数据,用Weapon解码依然不会报错——核心原因还是字段布局的兼容性。
可行的规避方案
- 手动添加类型前缀:序列化时在FlatBuffer字节数据前追加自定义类型标识(比如用
u8枚举:0代表Weapon,1代表Shield),解码前先读取前缀值,再选择对应的根类型解码。 - 使用FlatBuffer文件标识(File Identifier):在schema中给每个根类型设置专属文件标识,序列化时指定标识,解码时验证标识匹配性。
修改后的schema示例:
序列化时指定标识:file_identifier "WEAP"; table Weapon { name:string; damage:short; two_handed:bool; } root_type Weapon; file_identifier "SHLD"; table Shield { name:string; damage:short; } root_type Shield;
解码时通过sword_builder.finish(sword, Some(b"WEAP"));root_with_opts验证标识:
这种方式下,用错误类型解码会直接触发验证失败。let opts = flatbuffers::VerifierOptions { file_identifier: Some(b"WEAP"), ..Default::default() }; let sword_decoded = flatbuffers::root_with_opts::<schema::Weapon>(&sword_buffer, opts).unwrap();
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

