如果Visual studio 2012抛出一个在VS2012中不应该存在的编译错误,这意味着什么?

时间:2022-10-18 20:53:51

When I am compiling some class which uses boost serialization, I get compile error C2996, see below for the message itself. If I lookup this error, it seems that this error was thrown only by much older versions of the compiler. How can this be?

当我编译一些使用boost序列化的类时,我得到了编译错误C2996,下面是消息本身。如果我查找这个错误,那么这个错误似乎是由编译器的旧版本抛出的。这怎么可能?

The error message:

错误消息:

E:\Lib\boost_1_54_0\boost/serialization/split_member.hpp(42): error C2996: 'boost::hash_combine' : recursive function template definition

\Lib\ Lib\boost_1_54_0\boost/serialization/split_member.hpp(42): error C2996: 'boost: hash_combine':递归函数模板定义

VS2013, VS2012 and also VS2012 Update 4 showed this behaviour.

VS2013、VS2012和VS2012更新4显示了这种行为。

1 个解决方案

#1


4  

I had a similar problem. This seems to me like a bug in VS2012 (and above). I have been able to reproduce this in a simple .cpp file, so I opened a connect ticket.

我也有类似的问题。这在我看来像是VS2012(及以上)中的一个bug。我已经能够在一个简单的.cpp文件中复制它,所以我打开了一个连接票据。

I believe this error is erroneously reported when all of the following conditions apply:

我认为当所有下列条件都适用时,错误地报告此错误:

  1. An object is deserialized using Boost Serialization somewhere in the *.cpp file.
  2. 使用*中的某个地方的Boost序列化来反序列化对象。cpp文件。
  3. The serialized object is "deep enough" (~5 levels - i.e. A contains a vector of B, B contains a vector of C, etc. until E).
  4. 序列化的对象“足够深”(~5级——即A包含向量B, B包含向量C等,直到E)。
  5. Somewhere in the same *.cpp file (not necessarily in the same function), some templated function is called.
  6. 在同一个地方*。cpp文件(不一定在同一个函数中),会调用一些模板函数。

The error is no longer reported if the object is changed to be more "shallow", or if the call to the templated function is removed.

如果对象被更改为更“浅”,或者取消对模板函数的调用,则不再报告错误。

Also, this error does not reproduce in VS2010. I tested Boost versions 1.49, 1.52, 1.55.

同样,这个错误不会在VS2010中重现。我测试了Boost版本1.49,1.52,1.55。

Possible workaround: In one case, the error only appeared when we used boost::serialization::object_serializable (rather than the default object_class_info). Changing back to object_class_info may therefore be a workaround, except it will break backwards compatibility with previously serialized data.

可能的解决方案:在一种情况下,只有当我们使用boost:::序列化::object_serializable(而不是默认的object_class_info)时才出现错误。因此,将返回到object_class_info可能是一个解决方案,但它将破坏与以前序列化的数据的向后兼容性。

Possible workaround #2: hide the templated function call in a separate translation unit.

可能的解决方案2:将模板函数调用隐藏在一个单独的翻译单元中。

The following code reproduces the error:

以下代码重现错误:

/*
Download Boost from boost.org and extract into "boost_1_55_0".
Open VS2010 command prompt and build using the following command. It will build sucessfully.
cl BugC2996.cpp /c /EHsc /MD /I"boost_1_55_0"

Open VS2012 command prompt and build using the same command. It will fail with error C2996 on the line that calls UnrelatedTemplateFunc.
If you add EITHER of the following definitions to the command line, it will build successfully on VS2012:
/D "DONT_CALL_FUNC"
/D "SER_CLASS=B"

So it has something to do with the depth of the serialization, plus calling an unrelated templated function.

Please only compile, don't try to link - it will naturally fail. 
*/

#pragma warning(disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data (problem in Boost, unrelated to the bug in question)

#include <fstream>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/shared_ptr_132.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/utility.hpp>

struct E
{
    int x;
};

struct D
{
    std::vector<E> children;
};

struct C
{
    std::vector<D> children;
};

struct B
{
    std::vector<C> children;
};

struct A
{
    std::vector<B> children;
};


template<class Archive>
void serialize(Archive & ar, A& obj, const unsigned int /*file_version*/)
{
    ar & BOOST_SERIALIZATION_NVP(obj.children);
}

template<class Archive>
void serialize(Archive & ar, B& obj, const unsigned int /*file_version*/)
{
    ar & BOOST_SERIALIZATION_NVP(obj.children);
}

template<class Archive>
void serialize(Archive & ar, C& obj, const unsigned int /*file_version*/)
{
    ar & BOOST_SERIALIZATION_NVP(obj.children);
}

template<class Archive>
void serialize(Archive & ar, D& obj, const unsigned int /*file_version*/)
{
    ar & BOOST_SERIALIZATION_NVP(obj.children);
}

template<class Archive>
void serialize(Archive & ar, E& obj, const unsigned int /*file_version*/)
{
    ar & BOOST_SERIALIZATION_NVP(obj.x);
}



template<class T>
boost::shared_ptr<T> UnrelatedTemplateFunc(const std::string & argument);


#ifndef SER_CLASS
#define SER_CLASS A
#endif

// serialize A and the build will fail (if UnrelatedTemplateFunc is called below)
// serialize B instead of A and the build will succeed!
void Func(boost::shared_ptr<SER_CLASS> obj) 
{
    std::ifstream ifs;
    boost::archive::binary_iarchive ia(ifs);
    ia >> obj;
}

void OtherFunc()
{
    // comment this line and the build will succeed, whatever struct you decide to serialize above
    #ifndef DONT_CALL_FUNC
    UnrelatedTemplateFunc<unsigned char>("");
    #endif
}

#1


4  

I had a similar problem. This seems to me like a bug in VS2012 (and above). I have been able to reproduce this in a simple .cpp file, so I opened a connect ticket.

我也有类似的问题。这在我看来像是VS2012(及以上)中的一个bug。我已经能够在一个简单的.cpp文件中复制它,所以我打开了一个连接票据。

I believe this error is erroneously reported when all of the following conditions apply:

我认为当所有下列条件都适用时,错误地报告此错误:

  1. An object is deserialized using Boost Serialization somewhere in the *.cpp file.
  2. 使用*中的某个地方的Boost序列化来反序列化对象。cpp文件。
  3. The serialized object is "deep enough" (~5 levels - i.e. A contains a vector of B, B contains a vector of C, etc. until E).
  4. 序列化的对象“足够深”(~5级——即A包含向量B, B包含向量C等,直到E)。
  5. Somewhere in the same *.cpp file (not necessarily in the same function), some templated function is called.
  6. 在同一个地方*。cpp文件(不一定在同一个函数中),会调用一些模板函数。

The error is no longer reported if the object is changed to be more "shallow", or if the call to the templated function is removed.

如果对象被更改为更“浅”,或者取消对模板函数的调用,则不再报告错误。

Also, this error does not reproduce in VS2010. I tested Boost versions 1.49, 1.52, 1.55.

同样,这个错误不会在VS2010中重现。我测试了Boost版本1.49,1.52,1.55。

Possible workaround: In one case, the error only appeared when we used boost::serialization::object_serializable (rather than the default object_class_info). Changing back to object_class_info may therefore be a workaround, except it will break backwards compatibility with previously serialized data.

可能的解决方案:在一种情况下,只有当我们使用boost:::序列化::object_serializable(而不是默认的object_class_info)时才出现错误。因此,将返回到object_class_info可能是一个解决方案,但它将破坏与以前序列化的数据的向后兼容性。

Possible workaround #2: hide the templated function call in a separate translation unit.

可能的解决方案2:将模板函数调用隐藏在一个单独的翻译单元中。

The following code reproduces the error:

以下代码重现错误:

/*
Download Boost from boost.org and extract into "boost_1_55_0".
Open VS2010 command prompt and build using the following command. It will build sucessfully.
cl BugC2996.cpp /c /EHsc /MD /I"boost_1_55_0"

Open VS2012 command prompt and build using the same command. It will fail with error C2996 on the line that calls UnrelatedTemplateFunc.
If you add EITHER of the following definitions to the command line, it will build successfully on VS2012:
/D "DONT_CALL_FUNC"
/D "SER_CLASS=B"

So it has something to do with the depth of the serialization, plus calling an unrelated templated function.

Please only compile, don't try to link - it will naturally fail. 
*/

#pragma warning(disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data (problem in Boost, unrelated to the bug in question)

#include <fstream>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/shared_ptr_132.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/utility.hpp>

struct E
{
    int x;
};

struct D
{
    std::vector<E> children;
};

struct C
{
    std::vector<D> children;
};

struct B
{
    std::vector<C> children;
};

struct A
{
    std::vector<B> children;
};


template<class Archive>
void serialize(Archive & ar, A& obj, const unsigned int /*file_version*/)
{
    ar & BOOST_SERIALIZATION_NVP(obj.children);
}

template<class Archive>
void serialize(Archive & ar, B& obj, const unsigned int /*file_version*/)
{
    ar & BOOST_SERIALIZATION_NVP(obj.children);
}

template<class Archive>
void serialize(Archive & ar, C& obj, const unsigned int /*file_version*/)
{
    ar & BOOST_SERIALIZATION_NVP(obj.children);
}

template<class Archive>
void serialize(Archive & ar, D& obj, const unsigned int /*file_version*/)
{
    ar & BOOST_SERIALIZATION_NVP(obj.children);
}

template<class Archive>
void serialize(Archive & ar, E& obj, const unsigned int /*file_version*/)
{
    ar & BOOST_SERIALIZATION_NVP(obj.x);
}



template<class T>
boost::shared_ptr<T> UnrelatedTemplateFunc(const std::string & argument);


#ifndef SER_CLASS
#define SER_CLASS A
#endif

// serialize A and the build will fail (if UnrelatedTemplateFunc is called below)
// serialize B instead of A and the build will succeed!
void Func(boost::shared_ptr<SER_CLASS> obj) 
{
    std::ifstream ifs;
    boost::archive::binary_iarchive ia(ifs);
    ia >> obj;
}

void OtherFunc()
{
    // comment this line and the build will succeed, whatever struct you decide to serialize above
    #ifndef DONT_CALL_FUNC
    UnrelatedTemplateFunc<unsigned char>("");
    #endif
}