实现 "boost::serialization::load_construct_data "会引发一个内存访问违规错误。

问题描述 投票:1回答:1

我已经实现了对 boost::serialization::save_construct_databoost::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 与在《中国制造2025》中使用的《中国制造2025》不同,《中国制造2025》中使用的《中国制造2025》与《中国制造2025》中使用的《中国制造2025》不同。boost::serialization::load_construct_data 当呼叫安置新的运营商时。我希望它们是一样的。尽管如此,我不是专家,我不确定这是否与问题有关。只是想提供更多的,可能有用的信息。

谢谢你的帮助。

c++ boost-serialization placement-new
1个回答
0
投票

我很抱歉,我甚至把这个问题贴出来。我的实现有问题。我混淆了指数和实际值。正确的是下面这个。

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;
  auto lastIndexPrime = context->allPrimes().last();
  std::vector<long> primes(lastIndexPrime + 1);
  for(auto index = context->smallPrimes.first(); index <= context->smallPrimes.last(); index = context->smallPrimes.next(index))
    primes[index] = context->ithPrime(index);
  for(auto index = context->ctxtPrimes.first(); index <= context->ctxtPrimes.last(); index = context->ctxtPrimes.next(index))
    primes[index] = context->ithPrime(index);
  for(auto index = context->specialPrimes.first(); index <= context->specialPrimes.last(); index = context->specialPrimes.next(index))
    primes[index] = context->ithPrime(index);
  archive << primes;
}

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;
  std::vector<long> primes;
  archive >> m;
  archive >> p;
  archive >> r;
  archive >> smallPrimes;
  archive >> ctxtPrimes;
  archive >> specialPrimes;
  archive >> digits;
  archive >> primes;
  ::new(context)helib::Context(m, p, r);
  //restore smallPrimes
  for(long index = smallPrimes.first(); index <= smallPrimes.last(); index = smallPrimes.next(index))
    context->AddSmallPrime(primes[index]);
  //restore ctxtPrimes
  for(long index = ctxtPrimes.first(); index <= ctxtPrimes.last(); index = ctxtPrimes.next(index))
    context->AddCtxtPrime(primes[index]);
  //restore specialPrimes
  for(long index = specialPrimes.first(); index <= specialPrimes.last(); index = specialPrimes.next(index))
    context->AddSpecialPrime(primes[index]);
  //restore digits
  context->digits = digits;
  //last operation made in buildModchain
  endBuildModChain(*context);
}
© www.soinside.com 2019 - 2024. All rights reserved.