使用 Flatbuffer Union 导致双重释放或损坏错误
Use of Flatbuffer Union caused double free or corruption error
我在程序执行结束时遇到以下错误:
* Error in `./bin/test': double free or corruption (out): 0x00007ffd34dab0d0 *
Aborted
我目前正在测试 Flatbuffer for C++ 基于对象的 API (--gen-object-api)。我的主文件如下所示:
int main(int argc, char* argv[]) {
flatbuffers::FlatBufferBuilder builder;
auto dataTest = event::ByteBufferT();
dataTest.Bytes.push_back(1);
dataTest.Bytes.push_back(2);
event::EventDataUnion unionD;
unionD.type = event::EventData_ByteBuffer;
unionD.value = &dataTest;
auto eventOffset = event::CreateEvent(builder,
builder.CreateString("byteDataEvent"), 10,
event::EventData_ByteBuffer, unionD.Pack(builder));
builder.Finish(eventOffset);
auto eventOutput = event::GetEvent(builder.GetBufferPointer());
auto vec(eventOutput->data_as_ByteBuffer()->Bytes());
for (auto it = vec->begin(); it != vec->end(); ++it) {
std::cout << "ByteData: " << int(*it) << std::endl;
}
return 0;
}
我知道错误发生在哪里,但我不知道如何避免它。 valgrind 输出如下所示:
==6242== Invalid free() / delete / delete[] / realloc()
==6242== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==6242== by 0x4031C3: event::EventDataUnion::Reset() (event_generated.h:725)
==6242== by 0x4028F5: event::EventDataUnion::~EventDataUnion() (event_generated.h:78)
==6242== by 0x401320: main (main.cpp:118)
==6242== Address 0xfff0000d0 is on thread 1's stack
==6242== in frame #3, created by main (main.cpp:8)
==6242==
==6242== Invalid free() / delete / delete[] / realloc()
==6242== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==6242== by 0x406373: __gnu_cxx::new_allocator<signed char>::deallocate(signed char*, unsigned long) (new_allocator.h:110)
==6242== by 0x405FC6: std::allocator_traits<std::allocator<signed char> >::deallocate(std::allocator<signed char>&, signed char*, unsigned long) (alloc_traits.h:383)
==6242== by 0x40585D: std::_Vector_base<signed char, std::allocator<signed char> >::_M_deallocate(signed char*, unsigned long) (stl_vector.h:178)
==6242== by 0x404DA4: std::_Vector_base<signed char, std::allocator<signed char> >::~_Vector_base() (stl_vector.h:160)
==6242== by 0x403C5E: std::vector<signed char, std::allocator<signed char> >::~vector() (stl_vector.h:425)
==6242== by 0x403109: event::ByteBufferT::~ByteBufferT() (event_generated.h:260)
==6242== by 0x40132C: main (main.cpp:114)
==6242== Address 0x5a021d0 is 0 bytes inside a block of size 2 free'd
==6242== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==6242== by 0x406373: __gnu_cxx::new_allocator<signed char>::deallocate(signed char*, unsigned long) (new_allocator.h:110)
==6242== by 0x405FC6: std::allocator_traits<std::allocator<signed char> >::deallocate(std::allocator<signed char>&, signed char*, unsigned long) (alloc_traits.h:383)
==6242== by 0x40585D: std::_Vector_base<signed char, std::allocator<signed char> >::_M_deallocate(signed char*, unsigned long) (stl_vector.h:178)
==6242== by 0x404DA4: std::_Vector_base<signed char, std::allocator<signed char> >::~_Vector_base() (stl_vector.h:160)
==6242== by 0x403C5E: std::vector<signed char, std::allocator<signed char> >::~vector() (stl_vector.h:425)
==6242== by 0x403109: event::ByteBufferT::~ByteBufferT() (event_generated.h:260)
==6242== by 0x4031BB: event::EventDataUnion::Reset() (event_generated.h:725)
==6242== by 0x4028F5: event::EventDataUnion::~EventDataUnion() (event_generated.h:78)
==6242== by 0x401320: main (main.cpp:118)
==6242==
==6242==
==6242== HEAP SUMMARY:
==6242== in use at exit: 0 bytes in 0 blocks
==6242== total heap usage: 5 allocs, 7 frees, 1,219 bytes allocated
==6242==
==6242== All heap blocks were freed -- no leaks are possible
==6242==
==6242== For counts of detected and suppressed errors, rerun with: -v
==6242== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 1)
我的平面缓冲区文件 (event.fbs) 如下所示:
// event.fbs
namespace event;
table TableData {
param1:string;
param2:uint;
}
table ByteBuffer {
Bytes:[byte];
}
struct StructData {
x:float;
y:float;
}
union EventData {
TableData,
StructData,
ByteBuffer,
String:string,
}
table Event {
name:string (key);
timestamp:ulong = -1;
data:EventData;
}
root_type Event;
我的输出是正确的,除了错误:
ByteData: 1
ByteData: 2
*** Error in `./bin/test': double free or corruption (out): 0x00007ffd34dab0d0 ***
Aborted
更新:
如果没有对象 API 会像这样吗?:
flatbuffers::FlatBufferBuilder builder;
signed char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto byteBuffer = event::CreateByteBuffer(builder, builder.CreateVector(inv_data, 10));
auto event = event::CreateEvent(builder, builder.CreateString("byteDataEvent"), 10, event::EventData_ByteBuffer, byteBuffer.Union());
builder.Finish(event);
然后我会通过生成器?
错误可能在这里:
unionD.value = &dataTest;
联合对象期望拥有它指向的值,并在最后删除它。但是作为局部变量也被删除了。
您正在混合使用两个 API,对象 API(对于 ByteBuffer
和 EventData
)和标准 API(对于Event
)。这很好,但可能不是您想要的(前者用于 convenience/storage,后者用于速度)。对象 API 通常是一个自包含的对象树,它拥有自己的子对象。
我在程序执行结束时遇到以下错误:
* Error in `./bin/test': double free or corruption (out): 0x00007ffd34dab0d0 * Aborted
我目前正在测试 Flatbuffer for C++ 基于对象的 API (--gen-object-api)。我的主文件如下所示:
int main(int argc, char* argv[]) {
flatbuffers::FlatBufferBuilder builder;
auto dataTest = event::ByteBufferT();
dataTest.Bytes.push_back(1);
dataTest.Bytes.push_back(2);
event::EventDataUnion unionD;
unionD.type = event::EventData_ByteBuffer;
unionD.value = &dataTest;
auto eventOffset = event::CreateEvent(builder,
builder.CreateString("byteDataEvent"), 10,
event::EventData_ByteBuffer, unionD.Pack(builder));
builder.Finish(eventOffset);
auto eventOutput = event::GetEvent(builder.GetBufferPointer());
auto vec(eventOutput->data_as_ByteBuffer()->Bytes());
for (auto it = vec->begin(); it != vec->end(); ++it) {
std::cout << "ByteData: " << int(*it) << std::endl;
}
return 0;
}
我知道错误发生在哪里,但我不知道如何避免它。 valgrind 输出如下所示:
==6242== Invalid free() / delete / delete[] / realloc()
==6242== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==6242== by 0x4031C3: event::EventDataUnion::Reset() (event_generated.h:725)
==6242== by 0x4028F5: event::EventDataUnion::~EventDataUnion() (event_generated.h:78)
==6242== by 0x401320: main (main.cpp:118)
==6242== Address 0xfff0000d0 is on thread 1's stack
==6242== in frame #3, created by main (main.cpp:8)
==6242==
==6242== Invalid free() / delete / delete[] / realloc()
==6242== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==6242== by 0x406373: __gnu_cxx::new_allocator<signed char>::deallocate(signed char*, unsigned long) (new_allocator.h:110)
==6242== by 0x405FC6: std::allocator_traits<std::allocator<signed char> >::deallocate(std::allocator<signed char>&, signed char*, unsigned long) (alloc_traits.h:383)
==6242== by 0x40585D: std::_Vector_base<signed char, std::allocator<signed char> >::_M_deallocate(signed char*, unsigned long) (stl_vector.h:178)
==6242== by 0x404DA4: std::_Vector_base<signed char, std::allocator<signed char> >::~_Vector_base() (stl_vector.h:160)
==6242== by 0x403C5E: std::vector<signed char, std::allocator<signed char> >::~vector() (stl_vector.h:425)
==6242== by 0x403109: event::ByteBufferT::~ByteBufferT() (event_generated.h:260)
==6242== by 0x40132C: main (main.cpp:114)
==6242== Address 0x5a021d0 is 0 bytes inside a block of size 2 free'd
==6242== at 0x4C2A360: operator delete(void*) (vg_replace_malloc.c:507)
==6242== by 0x406373: __gnu_cxx::new_allocator<signed char>::deallocate(signed char*, unsigned long) (new_allocator.h:110)
==6242== by 0x405FC6: std::allocator_traits<std::allocator<signed char> >::deallocate(std::allocator<signed char>&, signed char*, unsigned long) (alloc_traits.h:383)
==6242== by 0x40585D: std::_Vector_base<signed char, std::allocator<signed char> >::_M_deallocate(signed char*, unsigned long) (stl_vector.h:178)
==6242== by 0x404DA4: std::_Vector_base<signed char, std::allocator<signed char> >::~_Vector_base() (stl_vector.h:160)
==6242== by 0x403C5E: std::vector<signed char, std::allocator<signed char> >::~vector() (stl_vector.h:425)
==6242== by 0x403109: event::ByteBufferT::~ByteBufferT() (event_generated.h:260)
==6242== by 0x4031BB: event::EventDataUnion::Reset() (event_generated.h:725)
==6242== by 0x4028F5: event::EventDataUnion::~EventDataUnion() (event_generated.h:78)
==6242== by 0x401320: main (main.cpp:118)
==6242==
==6242==
==6242== HEAP SUMMARY:
==6242== in use at exit: 0 bytes in 0 blocks
==6242== total heap usage: 5 allocs, 7 frees, 1,219 bytes allocated
==6242==
==6242== All heap blocks were freed -- no leaks are possible
==6242==
==6242== For counts of detected and suppressed errors, rerun with: -v
==6242== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 1)
我的平面缓冲区文件 (event.fbs) 如下所示:
// event.fbs
namespace event;
table TableData {
param1:string;
param2:uint;
}
table ByteBuffer {
Bytes:[byte];
}
struct StructData {
x:float;
y:float;
}
union EventData {
TableData,
StructData,
ByteBuffer,
String:string,
}
table Event {
name:string (key);
timestamp:ulong = -1;
data:EventData;
}
root_type Event;
我的输出是正确的,除了错误:
ByteData: 1
ByteData: 2
*** Error in `./bin/test': double free or corruption (out): 0x00007ffd34dab0d0 ***
Aborted
更新:
如果没有对象 API 会像这样吗?:
flatbuffers::FlatBufferBuilder builder;
signed char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto byteBuffer = event::CreateByteBuffer(builder, builder.CreateVector(inv_data, 10));
auto event = event::CreateEvent(builder, builder.CreateString("byteDataEvent"), 10, event::EventData_ByteBuffer, byteBuffer.Union());
builder.Finish(event);
然后我会通过生成器?
错误可能在这里:
unionD.value = &dataTest;
联合对象期望拥有它指向的值,并在最后删除它。但是作为局部变量也被删除了。
您正在混合使用两个 API,对象 API(对于 ByteBuffer
和 EventData
)和标准 API(对于Event
)。这很好,但可能不是您想要的(前者用于 convenience/storage,后者用于速度)。对象 API 通常是一个自包含的对象树,它拥有自己的子对象。