Повышенная загрузка сериализации завершается с ошибкой - PullRequest
4 голосов
/ 31 августа 2011

Я уже давно пытаюсь заставить эту работу работать.

В моем проекте есть 6 классов, которые сериализуются с использованием точного учебника от boost, путем реализации функции шаблона сериализации.

Эти классы: State, guState, Policy, Action, Param, Vec3D.

Когда я сериализую и сохраняю их, все работает нормально.Я действительно получаю текстовый файл с различными номерами и строками.

Никаких жалоб, никаких предупреждений, никаких исключений.Единственный случай, когда я пытаюсь сериализовать указатель на член класса, процесс с дырой становится зомби.Поэтому я не пытаюсь сделать это, и сохранение работает.

Когда, однако, я пытаюсь загрузить, я получаю:

прекращение вызова после бросания экземпляра 'boost :: archive ::archive_exception 'what (): ошибка потока

Теперь интересная часть состоит в том, что я сериализовал два boost :: ptr_vectors, один, который состоит из указателей состояния, а другой - из указателей политики.

Вектор состояния я сохранил и загрузил без проблем.Вектор политики я могу сохранить, но когда я пытаюсь загрузить, я получаю исключение.

Кроме того, после прочтения руководств по повышению у меня сложилось впечатление, что для загрузки мне не нужно ничего, кромефункция serialize.

Однако, когда я попытался загрузить, boost serialization жаловался на то, что не нашел конструктор по умолчанию, такой как State (), Policy () и т. д. (я реализую свои собственные конструкторы в каждом классе).

После прочтения этого урока здесь Я реализовал конструктор по умолчанию, который ничего не делает, чтобы Boost-сериализация работала.Действительно, он скомпилировался, и я получил результаты, упомянутые выше.

Я попытался пойти по очень сложной дороге, которую видел в мой старый вопрос здесь , где я попытался разделить и реализовать save_construct_data и load_construct_dataно я нашел это слишком навязчивым, опять же я получил точную ошибку, как указано выше.

Может кто-нибудь, пожалуйста, помогите мне, объясните, как работает загрузка, как обстоят дела с конструкторами по умолчанию?Или, по крайней мере, укажите мне ссылку, которая может быть полезной.Я просмотрел инструкции в boost, и они мало что объясняют о реконструкции.

Спасибо.

Редактировать (Добавлено несколько фрагментов)

class State
{
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version);

  protected:
    std::map<std::string,float> positions;
    float reward;
    std::size_t hash_value;
    bool exists(const Action* A);
    bool operator== (State const& S);
    std::size_t hash();
    void clean_noise();
    State(){}; // NOTE: This is used only by serializer, without it, code won't compile

  public:
    enum position { standing, on_chest, on_back, on_left, on_right, getting_up };
    position current_position;
    Policy *my_policy;
    Vec3D gps;
    boost::ptr_vector<Action> actions;
    State(ACTION_MODE &m);
    ~State();
    bool operator== (State const* S);
    bool operator< (State const* S) const ;
    const float& getR() const;
    bool addAction(Action *A);
    Action* findAction(const Action *A);
    boost::ptr_vector<Action>& getAllActions();
    void printState();
    virtual bool isTerm();
};

template <class Archive>
void State::serialize(Archive& ar, const unsigned int version)
{
  ar & BOOST_SERIALIZATION_NVP(positions);
  ar & BOOST_SERIALIZATION_NVP(gps);
  ar & BOOST_SERIALIZATION_NVP(current_position);
  ar & BOOST_SERIALIZATION_NVP(reward);
  ar & BOOST_SERIALIZATION_NVP(hash_value);
  ar & BOOST_SERIALIZATION_NVP(actions);
  ar & BOOST_SERIALIZATION_NVP(my_policy);
}

ДругоеКлассы, наследующие от State, также имеют свои функции сериализации, используя:

  ar & boost::serialization::base_object<State>(*this);

Class Policy:

class Policy
{ 
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version);

    Policy() {}; // NOTE: Again same as with state, used only by serialize load

  protected:

    float QValue;
    State *state;                

  public:

    //! Base class constructor 
    Policy(State *s);
    ...        
};

template <class Archive>
void Policy::serialize(Archive& ar, const unsigned int version)
{
  ar & BOOST_SERIALIZATION_NVP(action);
  ar & BOOST_SERIALIZATION_NVP(state);
  ar & BOOST_SERIALIZATION_NVP(QValue);
  ar & BOOST_SERIALIZATION_NVP(r);
}

Как вы видите, это два основных класса, Другие классы также сериализуются.из-за зависимостей восстановления (класс Action, класс Param и т. д.)

Мастер-класс:

template <class S, class P> class Task
{ 
  protected:
    ...
    //! Container of states of type S (template parameter)
    boost::ptr_vector<S> states;
    //! Container of policies of type P (template parameter)
    boost::ptr_vector<P> policies;
    ...

  public:

    Task(Agent &a, ACTION_MODE &m);
    ...
    void save_to_file();
    void load_from_file(std::string filename); 
};

template <class S, class P> 
void Task<S,P>::save_to_file()
{
  std::string output = ramdisk+"serialized";
  char *file = (char*)output.c_str();
  std::ofstream ofs(file);
  assert(ofs.good());  
  boost::archive::text_oarchive oa(ofs);
  oa << states;
  oa << policies;
  ofs.close();
}

template <class S, class P> 
void Task<S,P>::load_from_file(std::string filename)
{
  char *file = (char*)output.c_str();
  std::cout << file << std::endl;
  std::ifstream ifs(file);
  boost::archive::text_iarchive ia(ifs);
  ia >> states;
  ia >> policies;
  ifs.close();
}

Эффективно содержит два boost :: ptr_vectors, в которых хранятся состояния и политики.Состояния сохраняются и загружаются без проблем.

Проблема возникает при загрузке политик.Сохранение их, похоже, не создает проблемы (но, опять же, я могу ошибаться).

Протестировав сохранение / загрузку без политик и с помощью, проблема, похоже, связана с реконструкцией политики.

Обратите внимание на конструкторы по умолчанию, используемые только для сериализации, без которой код не будет компилироваться.

РЕДАКТИРОВАТЬ # 2: После запуска приложения с использованием valgrind и memcheck, он сообщает, что имеется утечка памяти указателя.Однако, поскольку я не очень хорош в отладке с помощью valgrind, я не могу точно сказать, где происходит утечка или имеет ли она отношение к моей сериализации (я так думаю).

1 Ответ

3 голосов
/ 05 сентября 2011

Проблема в том, что вы сериализуете states и policies, в то время как Policy также содержит ссылки на те же экземпляры State.Вы можете только сериализовать классы, которые не имеют таких перекрестных ссылок.Boost должен генерировать исключение конфликта указателей при записи в файл.В моих тестах это зависело от порядка записи, если было сгенерировано исключение или нет - что прискорбно, потому что загрузка не удалась, даже если запись прошла успешно.

В качестве обходного пути можно было бы удалить строку oa << states при сохранении и загрузке и исправить указатели вручную в шаге после загрузки.

О конструкторах: это в основном что-то повышающее-api должен сделать магию шаблона.Однако при использовании управления версиями важно указать значения по умолчанию для переменных-членов, чтобы они не оставались неинициализированными при загрузке файлов с более старым номером версии.

...