Хорошо, поэтому я столкнулся с проблемой в C++ 11 с зерном (http://uscilab.github.io/cereal/).Сериализация зерновых и полиморфизм
В абстрактном смысле у меня есть большой график, который я сериализую с большим количеством общих указателей, соединяющих ребра и вершины. Края (и вершины) также имеют прикрепленные к ним атрибуты.
Теперь одним из этих атрибутов (базового класса) является учетная запись (дочерний класс). Учетная запись также наследует от Idable, которая также является сериализуемой. Теперь вот некоторые подходящие фрагменты кода, которые показывают некоторые из моих возможностей использования злаков. Я объясню этот вопрос после этого контекста:
Attribute.hpp/CPP
class Attribute {
...
template<class Archive> void serialize(Archive&)
{
}
friend class cereal::access;
...
CEREAL_REGISTER_TYPE(mgraph::Attribute)
Idable.hpp/CPP
class Idable {
...
Id id;
template<class Archive> void serialize(Archive& archive)
{
archive(cereal::make_nvp("id", id));
}
template<class Archive> static void load_and_construct(Archive& ar, cereal::construct<mcommon::Idable>& construct)
{
mcommon::Id id;
ar(id);
construct(id);
}
friend class cereal::access;
...
CEREAL_REGISTER_TYPE(mcommon::Idable)
Position.hpp/CPP
class Position
: public mgraph::Attribute
, public mcommon::Displayable {
template<class Archive> void serialize(Archive& archive)
{
archive(cereal::make_nvp("Attribute",
cereal::base_class<mgraph::Attribute>(this)));
}
friend class cereal::access;
...
CEREAL_REGISTER_TYPE(mfin::Position)
Account.hpp/cpp
class Account
: public mcommon::Idable
, public Position {
...
Currency balance;
template<class Archive> void serialize(Archive& archive)
{
archive(cereal::make_nvp("Idable",
cereal::base_class<mcommon::Idable>(this)),
cereal::make_nvp("Position",
cereal::base_class<mfin::Position>(this)),
cereal::make_nvp("balance", balance));
}
template<class Archive> static void load_and_construct(Archive& ar, cereal::construct<Account>& construct)
{
mcommon::Id iden;
Currency::Code code;
ar(iden, code);
construct(iden, code);
}
friend class cereal::access;
...
CEREAL_REGISTER_TYPE(mfin::Account)
Таким образом, проблема возникает, когда mfin :: Account сериализуется. Mfin :: Account принадлежит к std :: list>. Когда мы переходим к функции сериализации для Idable, объект недействителен.
Переход в gdb, который останавливается на segfault. Я поднимаю несколько стековых кадров к этой строке: /usr/include/cereal/types/polymorphic.hpp:341. Что:
(gdb) list
336
337 auto binding = bindingMap.find(std::type_index(ptrinfo));
338 if(binding == bindingMap.end())
339 UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name()))
340
341 binding->second.shared_ptr(&ar, ptr.get());
342 }
343
344 //! Loading std::shared_ptr for polymorphic types
345 template <class Archive, class T> inline
Теперь вот это то, что PTR является:
(gdb) print *((mfin::Account*)(ptr.get()))
$10 = {<mcommon::Idable> = {_vptr.Idable = 0x4f0d50 <vtable for mfin::Account+16>, id = "bank"}, <mfin::Position> = {<mgraph::Attribute> = {
_vptr.Attribute = 0x4f0d78 <vtable for mfin::Account+56>}, <mcommon::Displayable> = {_vptr.Displayable = 0x4f0da0 <vtable for mfin::Account+96>}, <No data fields>}, balance = {<mcommon::Displayable> = {
_vptr.Displayable = 0x4f0570 <vtable for mfin::Currency+16>}, amount = 0, code = mfin::Currency::USD}}
(gdb) print ptr
$11 = std::shared_ptr (count 3, weak 0) 0x758ad0
Все выглядит хорошо. Но обратите внимание, когда я бросил его в ничтожном *:
$11 = std::shared_ptr (count 3, weak 0) 0x758ad0
(gdb) print *((mfin::Account*)((void*)ptr.get()))
$12 = {<mcommon::Idable> = {_vptr.Idable = 0x4f0d78 <vtable for mfin::Account+56>,
id = "\363aL\000\000\000\000\000PbL\000\000\000\000\000\304\031L\000\000\000\000\000\021#L", '\000' <repeats 13 times>, " \232N", '\000' <repeats 21 times>, "P\[email protected]\000\000\000\000\000\370\377\377\377\377\377\377\377 \232N", '\000' <repeats 21 times>, "\304\031L\000\000\000\000\000P\[email protected]", '\000' <repeats 45 times>, "St19_Sp_counted_deleterIPN4mfin7AccountE"...}, <mfin::Position> = {<mgraph::Attribute> = {
_vptr.Attribute = 0x4f0570 <vtable for mfin::Currency+16>}, <mcommon::Displayable> = {_vptr.Displayable = 0x0}, <No data fields>}, balance = {<mcommon::Displayable> = {_vptr.Displayable = 0x0}, amount = 49,
code = (unknown: 7702648)}}
Это, конечно, что происходит в binding-> second.shared_ptr (показано ниже), который принимает константную пустоту *.
(gdb) list
295 writeMetadata(ar);
296
297 #ifdef _MSC_VER
298 savePolymorphicSharedPtr(ar, dptr, ::cereal::traits::has_shared_from_this<T>::type()); // MSVC doesn't like typename here
299 #else // not _MSC_VER
300 savePolymorphicSharedPtr(ar, dptr, typename ::cereal::traits::has_shared_from_this<T>::type());
301 #endif // _MSC_VER
302 };
303
304 serializers.unique_ptr =
Что не так в моем использовании зерновых, которые могут вызвать это? Вот окончательная ошибка, которую я получаю:
Program received signal SIGSEGV, Segmentation fault.
0x000000000040f7cd in rapidjson::Writer<rapidjson::GenericWriteStream, rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >::WriteString (this=0x7fffffffd358,
str=0x4f1ae0 <vtable for mfin::Account+96> "\363aL", length=4989722) at /usr/include/cereal/external/rapidjson/writer.h:276
276 if ((sizeof(Ch) == 1 || characterOk(*p)) && escape[(unsigned char)*p]) {
Missing separate debuginfos, use: debuginfo-install boost-date-time-1.55.0-8.fc21.x86_64 boost-filesystem-1.55.0-8.fc21.x86_64 boost-program-options-1.55.0-8.fc21.x86_64 boost-system-1.55.0-8.fc21.x86_64 boost-thread-1.55.0-8.fc21.x86_64 fcgi-2.4.0-24.fc21.x86_64 glog-0.3.3-3.128tech.x86_64 libgcc-4.9.2-1.fc21.x86_64 libstdc++-4.9.2-1.fc21.x86_64
FYI, * "cereal" * - это еда, основанная на зерне, обычно съедается на завтрак. «Serial» - это процесс передачи одной вещи за раз, например, бит на жесткий диск. –
это также название библиотеки, http://uscilab.github.io/cereal/, спасибо, хотя –
Спасибо! . Теперь я жажду петли Froot! –