Я реализовал пару boost::serialization::save_construct_data
и boost::serialization::load_construct_data
для класса, у которого нет конструктора по умолчанию (helib::Context
). В реализации boost::serialization::load_construct_data
я должен вызвать некоторые методы сериализуемого класса. К сожалению, когда я обращаюсь к указателю, я получаю следующую ошибку во время выполнения:
memory access violation at address: 0x00000000: no mapping at fault address
Реализация следующая:
namespace boost{
namespace serialization{
template<class Archive>
inline void save_construct_data(Archive & archive, const helib::Context * context, const unsigned int version){
archive << context->zMStar.getM();
archive << context->zMStar.getP();
archive << context->alMod.getR();
archive << context->smallPrimes;
archive << context->ctxtPrimes;
archive << context->specialPrimes;
archive << context->digits;
}
template<class Archive>
inline void load_construct_data(Archive & archive, helib::Context * context, const unsigned int version){
unsigned long m;
unsigned long p;
unsigned long r;
helib::IndexSet smallPrimes;
helib::IndexSet ctxtPrimes;
helib::IndexSet specialPrimes;
std::vector<helib::IndexSet> digits;
archive >> m;
archive >> p;
archive >> r;
archive >> smallPrimes;
archive >> ctxtPrimes;
archive >> specialPrimes;
archive >> digits;
::new(context)helib::Context(m, p, r);
//restore smallPrimes
for(long prime = smallPrimes.first(); prime <= smallPrimes.last(); prime = smallPrimes.next(prime)){
context->AddSmallPrime(prime);
}
//restore ctxtPrimes
for(long prime = ctxtPrimes.first(); prime <= ctxtPrimes.last(); prime = ctxtPrimes.next(prime))
context->AddCtxtPrime(prime);
//restore specialPrimes
for(long prime = specialPrimes.first(); prime <= specialPrimes.last(); prime = specialPrimes.next(prime))
context->AddSpecialPrime(prime);
//restore digits
context->digits = digits;
//last operation made in buildModchain
context->setModSizeTable();
}
template<class Archive>
void serialize(Archive & archive, helib::Context & context, const unsigned int version){}
}//namespace boost
}//namespace serialization
и вот тест, вызывающий код:
BOOST_AUTO_TEST_CASE(serialization_context)
{
// Plaintext prime modulus
unsigned long p = 4999;
// Cyclotomic polynomial - defines phi(m)
unsigned long m = 32109;
// Hensel lifting (default = 1)
unsigned long r = 1;
// Number of bits of the modulus chain
unsigned long bits = 300;
// Number of columns of Key-Switching matix (default = 2 or 3)
unsigned long c = 2;
helib::Context * original_context_ptr = new helib::Context(m, p, r);
// Modify the context, adding primes to the modulus chain
buildModChain(*original_context_ptr, bits, c);
std::string filename = "context.serialized";
std::ofstream os(filename);
{
boost::archive::text_oarchive oarchive(os);
BOOST_TEST_MESSAGE("(m,p,r): " << original_context_ptr->zMStar.getM() << "," << original_context_ptr->zMStar.getP() << "," << original_context_ptr->alMod.getR());
oarchive << original_context_ptr;
}
helib::Context * restored_context_ptr = new helib::Context(2, 3, 1);
BOOST_TEST_MESSAGE("allocated memory for restored context, address " << restored_context_ptr);
{
std::ifstream ifs(filename);
boost::archive::text_iarchive iarchive(ifs);
iarchive >> restored_context_ptr;
BOOST_TEST_MESSAGE("(m,p,r): " << restored_context_ptr->zMStar.getM() << "," << restored_context_ptr->zMStar.getP() << "," << restored_context_ptr->alMod.getR());
}
BOOST_TEST((*restored_context_ptr == *original_context_ptr));
}
Как видно из кода, я поместил несколько сообщений, чтобы попытаться диагностировать проблему. Когда я запускаю тест, я получаю следующее:
Running 2 test cases...
(m,p,r): 32109,4999,1
allocated memory for restored context, address 0x7fa7c060acb0
context instantiated, address 0x7fa7c060bff0
unknown location:0: fatal error: in "serialization_context": memory access violation at address: 0x00000000: no mapping at fault address
/Users/gianca/electronic-voting-poc/serialization.hpp:68: last checkpoint: adding small prime 0
Test is aborted
Test is aborted
Две вещи:
Последняя информация о контрольной точке в сообщении выше говорит о том, что ошибка возникает при выполнении context->AddSmallPrime(prime);
внутри функции load_construct_data
. (Я стер BOOST_TEST_CHECKPOINT
из приведенного выше кода для ясности).
Я был удивлен, увидев, что адрес, выделенный для получения восстановленного helib::Context
, не совпадает с адресом используется внутри boost::serialization::load_construct_data
при вызове оператора new для размещения. Я ожидал, что они будут такими же. Тем не менее, я не специалист и не уверен, что это связано с проблемой. Просто хотел дать больше, возможно, полезной информации.
Спасибо за любую помощь.