构建器被销毁时缓冲区有效吗?

时间:2019-04-10 09:17:42

标签: c++ serialization flatbuffers

我正在使用平面缓冲区对对象进行序列化以通过网络传输,问题是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有效的内存缓冲区吗?谢谢。

2 个答案:

答案 0 :(得分:1)

您对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将拥有底层的缓冲存储器,并在调用析构函数后将其释放。

答案 1 :(得分:1)

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,但是您需要处理释放内存的事实。由你决定。