当构建器被销毁时,缓冲区是否有效

Is buffer valid when the builder is destroyed?

本文关键字:缓冲区 是否 有效 构建      更新时间:2023-10-16

我正在使用平面缓冲区对对象进行序列化以通过网络传输,问题是在FlatBufferBuild超出范围后缓冲区是否仍然有效,例如:

char* GetBuffer(...size_t &size) {
    flatbuffers::FlatBufferBuilder fbb;
    flatbuffers::Offset<MyStruct> data = CreateMyStruct(fbb, ...);
    FinishMyStructBuffer(fbb, data);
    size = fbb.GetSize();
    return fbb.GetBufferPointer();
}
size_t size;
char* mybuf = GetBuffer(..., size);
do(mybuf, size);

我使用mybuf内存缓冲区是否有效?谢谢。

FlatBufferBuilder类使用自定义类作为保存数据的基础数组。该类本身称为flatbuffers::vector_downward,文档说:

这是 std::vector 功能的最小复制,除了从高地址增长到低地址。

该类遵循 RAII 的原则,因此析构函数正在处理作业以释放分配的数据。

~vector_downward() {
    clear_buffer();
    clear_allocator();
}

因此,基本上,您正在访问在离开函数作用域时已取消分配的内存。

现在有很多替代方案可以解决这个问题。我将亲自避免函数中的另一个参数并创建自定义构建器。像这样:

struct MyStructBuilder {
    char* GetBuffer(..., size_t &size) {
        flatbuffers::Offset<MyStruct> data = CreateMyStruct(fbb, ...);
        FinishMyStructBuffer(fbb, data);
        size = fbb.GetSize();
        return fbb.GetBufferPointer();
    }
private:
    flatbuffers::FlatBufferBuilder fbb;
};
MyStructBuilder builder;
size_t size;
char* mybuf = builder.GetBuffer(..., size);
do(mybuf, size);

或者你可以使用 FlatBufferBuilder::Release ,但您需要处理释放内存的事实。这取决于你。

您对mybuf的使用是无效的,它将导致未定义的行为,因为FlatBufferBuilder在调用其析构函数时会破坏内部缓冲区。我建议按如下方式使用DetachedBuffer

flatbuffers::DetachedBuffer GetBuffer(...) {
    flatbuffers::FlatBufferBuilder fbb;
    flatbuffers::Offset<MyStruct> data = CreateMyStruct(fbb, ...);
    FinishMyStructBuffer(fbb, data);
    return fbb.Release();
}
flatbuffers::DetachedBuffer mybuf = GetBuffer(...);
do(mybuf);

请注意,DetachedBuffer将拥有基础缓冲区内存,并在调用析构函数后释放它。