Coding Memo
[FlatBuffers] nested 에러 (nested was true) 본문
Error
Create~~를 이용해 flatbuffer관련 객체나 구조체를 생성할 때 나타나는 에러이다.
assert에 의한 에러이다.
Problem
다음은 문제의 코드이다. CreateString을 이용해 flatbuffer 문자열을 만드는 중에 에러가 발생했다.
#pragma comment(lib, "Release\\flatbuffers.lib")
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/util.h"
#include "flatbuffers_scehmas/MyGame_generated.h"
#include <iostream>
using namespace std;
using namespace MyGame;
int main()
{
// error codes
{
flatbuffers::FlatBufferBuilder builder;
Vec3 pos(0, 0, 0);
// same as CreateMonster()
MonsterBuilder mb(builder);
auto name = builder.CreateString("Skeleton"); // error here
mb.add_hp(2000);
mb.add_name(name);
mb.add_pos(&pos);
auto monster = mb.Finish();
builder.Finish(monster);
// deserialize
auto buf = builder.GetBufferPointer();
auto data = MyGame::GetMonster(buf);
cout << data->hp() << endl;
cout << data->name()->str() << endl;
}
return 0;
}
Solution
`Create`를 이용한 flatbuffer 구조체 생성 시(직렬화 시) 중에 `CreateString`을 호출하지 말고 그 전에 호출하여 가지고 있자.
int main()
{
// error codes
{
flatbuffers::FlatBufferBuilder builder;
// CreateMonster() 전에 호출
auto name = builder.CreateString("Skeleton");
Vec3 pos(0, 0, 0);
// same as CreateMonster()
MonsterBuilder mb(builder); // 이후 builder.nested = true
mb.add_hp(2000);
mb.add_name(name);
mb.add_pos(&pos);
auto monster = mb.Finish(); // 이후 builder.nested = false
// 아니면 아래와 같이 처음부터 호출해도 OK
// 순서상 CreateString이 먼저 호출되니까...!
// auto monster = CreateMonster(builder, &pos, 100, 1000, builder.CreateString("Skeleton"));
builder.Finish(monster);
// deserialize
auto buf = builder.GetBufferPointer();
auto data = MyGame::GetMonster(buf);
cout << data->hp() << endl;
cout << data->name()->str() << endl;
}
return 0;
}
`Create`를 이용한 flatbuffer 구조체 생성 시(직렬화 시) 중에는 Finish 전까지 다른 구조체나 벡터를 생성하면 안된다.
flatbuffer 구조체를 Create하고 있을 때에는 `flatbuffers::FlatBufferBuilder`의 nested 값이 true가 된다. 이 상태에서는 특정 버퍼 위치에 해당 구조체를 직렬화하고 있는 상태이기 때문에 이 빌더를 이용하여 다른 값을 만들어서는 안된다.
nested 상태일 때, CreateString을 호출하면 내부적으로 다음이 순서대로 호출된다. (일부 생략)
/// @brief Store a string in the buffer, which can contain any binary data.
/// @param[in] str A const char pointer to the data to be stored as a string.
/// @param[in] len The number of bytes that should be stored from `str`.
/// @return Returns the offset in the buffer where the string starts.
void CreateStringImpl(const char *str, size_t len) {
NotNested();
PreAlign<uoffset_t>(len + 1); // Always 0-terminated.
buf_.fill(1);
PushBytes(reinterpret_cast<const uint8_t *>(str), len);
PushElement(static_cast<uoffset_t>(len));
}
NotNested()
void NotNested() {
// If you hit this, you're trying to construct a Table/Vector/String
// during the construction of its parent table (between the MyTableBuilder
// and table.Finish().
// Move the creation of these sub-objects to above the MyTableBuilder to
// not get this assert.
// Ignoring this assert may appear to work in simple cases, but the reason
// it is here is that storing objects in-line may cause vtable offsets
// to not fit anymore. It also leads to vtable duplication.
FLATBUFFERS_ASSERT(!nested);
// If you hit this, fields were added outside the scope of a table.
FLATBUFFERS_ASSERT(!num_field_loc);
}
위에도 이유가 작성되어 있다.
FLATBUFFERS_ASSERT(!nested) 부분에서 에러가 난다.
즉, `Create[flabuffer struct]`를 실행시키고 Finish가 되기 전까지 `CreateString()`등의 메서드를 호출하여 다른 벡터나 객체를 만들면 안된다.
'Language > C++' 카테고리의 다른 글
[메모] const 함수 유의사항 (C2665 에러 등) (0) | 2024.04.16 |
---|---|
[Winsock] WSAEINVAL(10022) 에러 (ConnectEx) (0) | 2024.03.25 |
[C++] 가상 소멸자 (0) | 2024.03.06 |
[C++] pack pragma (메모리 정렬) (0) | 2024.03.05 |
Use After Free (0) | 2023.11.02 |