Search code examples
c++serializationflatbuffers

Is buffer valid when the builder is destroyed?


I'm using flatbuffers for serialisation of objects to transfer over network, question is whether the buffer remains valid after the FlatBufferBuild is out of scope, for example:

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);

Is my usage of mybuf valid memory buffer? Thanks.


Solution

  • The FlatBufferBuilder class is using a custom class as the underlying array that holds the data. The class itself is called flatbuffers::vector_downward and the documentation says:

    This is a minimal replication of std::vector functionality, except growing from higher to lower addresses.

    The class follows the principles of RAII, so the destructor is handling the job to release the allocated data.

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

    So basically, you are accessing to a memory that has been de-allocate when leaving the function scope.

    Now there are plenty of alternatives to solve this problem. I will personally avoid another argument in a function and create a custom builder. Something like this:

    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);
    

    Or you can use FlatBufferBuilder::Release, but you will need to deal with the fact of releasing the memory. It's up to you.