2013-12-02 2 views
1

Я представляю базовые блоки кода и поток управления между ними как циклический граф и хочу иметь возможность сериализовать график на XML или аналогичный, а затем десериализировать его и использовать график в другое приложение. При попытке сериализации структуры данных я получаю тысячи вызовов функции сериализации, хотя граф, который я использую для тестирования приложения, содержит менее пятидесяти узлов, что заставляет меня думать, что проблема связана с циклическими ссылками.Сериализовать циклические графики с BOOST в C++

Когда я запускаю или отлаживает приложение, он успешно повторно вводит функцию void serialize(Archive&, std::vector<BasicBlock*>&, const unsigned), пока не сработает с ошибкой сегментации. Выходной файл создается, но на него ничего не записывается.

Ниже приведена структура данных, которую я использую для представления основных блоков;

struct __attribute__ ((visibility ("default"))) BasicBlock { 
    unsigned int id; 
    unsigned int start_address; 
    unsigned int end_address; 
    std::vector<BasicBlock*>* outgoing; 
    std::vector<BasicBlock*>* incoming; 
}; 

и это класс сериализации и функции

class Serialize { 
public: 

    static void marshal(const std::vector<BasicBlock*>& basic_blocks, std::string filename) { 
     std::ofstream ofstream(filename.c_str(), std::ios::out | std::ios::binary); 
     boost::archive::text_oarchive archive(ofstream); 
     archive << basic_blocks; 
    } 

    static void unmarshal(const std::string filename, std::vector<BasicBlock*>& basic_blocks) { 
     std::ifstream ifstream(filename.c_str()); 
     boost::archive::text_iarchive archive(ifstream); 
     archive >> basic_blocks; 
    } 

}; 

namespace boost { 
    namespace serialization { 

    template<class Archive> 
    void save(Archive & archive, const BasicBlock& basic_block, const unsigned int version) { 
     archive & basic_block.id; 
     archive & basic_block.start_address; 
     archive & basic_block.end_address; 
     archive & basic_block.incoming; 
     archive & basic_block.outgoing; 
    } 

    template<class Archive> 
    void load(Archive & archive, BasicBlock& basic_block, const unsigned int version) { 
     archive & basic_block.id; 
     archive & basic_block.start_address; 
     archive & basic_block.end_address; 
     archive & basic_block.incoming; 
     archive & basic_block.outgoing; 
    } 

    template<typename Archive> 
    void serialize(Archive& archive, std::vector<BasicBlock>& basic_blocks, const unsigned version) { 
     archive & basic_blocks; 
    } 

    template<typename Archive> 
    void serialize(Archive& archive, std::vector<BasicBlock*>& basic_blocks, const unsigned version) { 
     archive & basic_blocks; // Triggered thousands of times... 
    } 

    } 
} 

BOOST_SERIALIZATION_SPLIT_FREE(BasicBlock) 

ответ

1

Моя первая подозрение, что «спасти» перегружает для vector с фактически разрушить вещи для вас.

template<typename Archive> 
    void serialize(Archive& archive, std::vector<BasicBlock*>& basic_blocks, const unsigned version) { 
     archive & basic_blocks; // Triggered thousands of times... 
    } 

бы ... (косвенно) рекурсивно вызывать себя AFAICT

Пробовали ли вы в том числе boost/serialization/vector.hpp?

Вот SSCCE, что показывает, что он работает: Посмотреть Live on Coliru

#include <boost/serialization/vector.hpp> 
#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <vector> 
#include <fstream> 

struct BasicBlock { 
    unsigned int id; 
    unsigned int start_address; 
    unsigned int end_address; 
    std::vector<BasicBlock*>* outgoing; 
    std::vector<BasicBlock*>* incoming; 
}; 

// BOOST_CLASS_TRACKING(BasicBlock, boost::serialization::track_always) 

namespace boost { 
    namespace serialization { 
     template<class Archive> 
      void save(Archive & archive, const BasicBlock& basic_block, const unsigned int version) { 
       archive & basic_block.id; 
       archive & basic_block.start_address; 
       archive & basic_block.end_address; 
       archive & basic_block.incoming; 
       archive & basic_block.outgoing; 
      } 

     template<class Archive> 
      void load(Archive & archive, BasicBlock& basic_block, const unsigned int version) { 
       archive & basic_block.id; 
       archive & basic_block.start_address; 
       archive & basic_block.end_address; 
       archive & basic_block.incoming; 
       archive & basic_block.outgoing; 
      } 
    } 
} 

BOOST_SERIALIZATION_SPLIT_FREE(BasicBlock) 

int main() 
{ 
    BasicBlock root 
    { 
     1, 2, 3, 
     new std::vector<BasicBlock*> { new BasicBlock { 4, 5, 6, nullptr, nullptr } }, 
     new std::vector<BasicBlock*> { &root } // cyclic! 
    }; 

    boost::archive::text_oarchive ar(std::cout); 
    ar << root; 

    // everything leaked :) 
} 
+1

Вы были правы, спасибо так много. Это становится немного проблематичным, когда вы (я) включаете огромную структуру в проект и просто принимаете все волшебные вещи, которые внезапно предоставляются. Не думайте, что я когда-либо выяснял, что это был рекурсивный вызов сам по себе. –

Смежные вопросы