提升序列化:可以安全地忽略警告?
Posted
技术标签:
【中文标题】提升序列化:可以安全地忽略警告?【英文标题】:Boost serialization: safe to ignore warning? 【发布时间】:2011-03-28 09:56:28 【问题描述】:我开始使用boost的序列化代码将数据写入二进制流。我收到以下可以禁用的警告 (D_SCL_SECURE_NO_WARNINGS
) 但我想知道这样做是否安全?如何获得更具体的信息,我的代码导致警告?我只知道 .cpp 文件。
这是 Visual Studio 2008 的输出:
4>g:\winlib\boost\1_42_0\boost/archive/basic_binary_iprimitive.hpp(162) : warng C4996: 'std::basic_streambuf<_Elem,_Traits>::sgetn': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
4> with
4> [
4> _Elem=char,
4> _Traits=std::char_traits<char>
4> ]
4> E:\Visual Studio 9.0\VC\include\streambuf(121) : see declaration of 'std::basic_streambuf<_Elem,_Traits>::sgetn'
4> with
4> [
4> _Elem=char,
4> _Traits=std::char_traits<char>
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/basic_binary_iprimitive.hpp(152) : while compiling class template member function 'void boost::archive::basic_binary_iprimitive<Archive,Elem,Tr>::load_binary(void *,size_t)'
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> Elem=char,
4> Tr=std::char_traits<char>
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/iserializer.hpp(107) : see reference to function template instantiation 'void boost::archive::basic_binary_iprimitive<Archive,Elem,Tr>::load<T>(T &)' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> Elem=char,
4> Tr=std::char_traits<char>,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/iserializer.hpp(356) : see reference to function template instantiation 'void boost::archive::load_access::load_primitive<Archive,T>(Archive &,T &)' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/iserializer.hpp(433) : see reference to function template instantiation 'void boost::archive::detail::load_non_pointer_type<Archive>::load_primitive::invoke<T>(Archive &,T &)' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/iserializer.hpp(580) : see reference to function template instantiation 'void boost::archive::detail::load_non_pointer_type<Archive>::invoke<T>(Archive &,T &)' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/common_iarchive.hpp(68) : see reference to function template instantiation 'void boost::archive::load<Archive,T>(Archive &,T &)' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/basic_binary_iarchive.hpp(67) : see reference to function template instantiation 'void boost::archive::detail::common_iarchive<Archive>::load_override<T>(T &,int)' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/binary_iarchive_impl.hpp(50) : see reference to function template instantiation 'void boost::archive::basic_binary_iarchive<Archive>::load_override<T>(T &,int)' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/interface_iarchive.hpp(61) : see reference to function template instantiation 'void boost::archive::binary_iarchive_impl<Archive,Elem,Tr>::load_override<T>(T &,int)' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> Elem=char,
4> Tr=std::char_traits<char>,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/basic_binary_iarchive.hpp(77) : see reference to function template instantiation 'Archive &boost::archive::detail::interface_iarchive<Archive>::operator >><unsigned char>(T &)' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/basic_binary_iarchive.hpp(74) : while compiling class template member function 'void boost::archive::basic_binary_iarchive<Archive>::load_override(boost::archive::version_type &,int)'
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/binary_iarchive_impl.hpp(36) : see reference to class template instantiation 'boost::archive::basic_binary_iarchive<Archive>' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/binary_iarchive.hpp(42) : see reference to class template instantiation 'boost::archive::binary_iarchive_impl<Archive,Elem,Tr>' being compiled
4> with
4> [
4> Archive=boost::archive::naked_binary_iarchive,
4> Elem=char,
4> Tr=std::char_traits<char>
4> ]
4>g:\winlib\boost\1_42_0\boost/archive/basic_binary_iprimitive.hpp(176) : warning C4996: 'std::basic_streambuf<_Elem,_Traits>::sgetn': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
4> with
4> [
4> _Elem=char,
4> _Traits=std::char_traits<char>
4> ]
4> E:\Visual Studio 9.0\VC\include\streambuf(121) : see declaration of 'std::basic_streambuf<_Elem,_Traits>::sgetn'
4> with
4> [
4> _Elem=char,
4> _Traits=std::char_traits<char>
4> ]
4>g:\winlib\boost\1_42_0\boost/archive/basic_binary_iprimitive.hpp(162) : warning C4996: 'std::basic_streambuf<_Elem,_Traits>::sgetn': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
4> with
4> [
4> _Elem=char,
4> _Traits=std::char_traits<char>
4> ]
4> E:\Visual Studio 9.0\VC\include\streambuf(121) : see declaration of 'std::basic_streambuf<_Elem,_Traits>::sgetn'
4> with
4> [
4> _Elem=char,
4> _Traits=std::char_traits<char>
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/basic_binary_iprimitive.hpp(152) : while compiling class template member function 'void boost::archive::basic_binary_iprimitive<Archive,Elem,Tr>::load_binary(void *,size_t)'
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> Elem=char,
4> Tr=std::char_traits<char>
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/iserializer.hpp(107) : see reference to function template instantiation 'void boost::archive::basic_binary_iprimitive<Archive,Elem,Tr>::load<T>(T &)' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> Elem=char,
4> Tr=std::char_traits<char>,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/iserializer.hpp(356) : see reference to function template instantiation 'void boost::archive::load_access::load_primitive<Archive,T>(Archive &,T &)' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/iserializer.hpp(433) : see reference to function template instantiation 'void boost::archive::detail::load_non_pointer_type<Archive>::load_primitive::invoke<T>(Archive &,T &)' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/iserializer.hpp(580) : see reference to function template instantiation 'void boost::archive::detail::load_non_pointer_type<Archive>::invoke<T>(Archive &,T &)' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/common_iarchive.hpp(68) : see reference to function template instantiation 'void boost::archive::load<Archive,T>(Archive &,T &)' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/basic_binary_iarchive.hpp(67) : see reference to function template instantiation 'void boost::archive::detail::common_iarchive<Archive>::load_override<T>(T &,int)' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/binary_iarchive_impl.hpp(50) : see reference to function template instantiation 'void boost::archive::basic_binary_iarchive<Archive>::load_override<T>(T &,int)' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/detail/interface_iarchive.hpp(61) : see reference to function template instantiation 'void boost::archive::binary_iarchive_impl<Archive,Elem,Tr>::load_override<T>(T &,int)' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> Elem=char,
4> Tr=std::char_traits<char>,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/basic_binary_iarchive.hpp(77) : see reference to function template instantiation 'Archive &boost::archive::detail::interface_iarchive<Archive>::operator >><unsigned char>(T &)' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> T=unsigned char
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/basic_binary_iarchive.hpp(74) : while compiling class template member function 'void boost::archive::basic_binary_iarchive<Archive>::load_override(boost::archive::version_type &,int)'
4> with
4> [
4> Archive=boost::archive::binary_iarchive
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/binary_iarchive_impl.hpp(36) : see reference to class template instantiation 'boost::archive::basic_binary_iarchive<Archive>' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive
4> ]
4> g:\winlib\boost\1_42_0\boost/archive/binary_iarchive.hpp(76) : see reference to class template instantiation 'boost::archive::binary_iarchive_impl<Archive,Elem,Tr>' being compiled
4> with
4> [
4> Archive=boost::archive::binary_iarchive,
4> Elem=char,
4> Tr=std::char_traits<char>
4> ]
4>g:\winlib\boost\1_42_0\boost/archive/basic_binary_iprimitive.hpp(176) : warning C4996: 'std::basic_streambuf<_Elem,_Traits>::sgetn': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
4> with
4> [
4> _Elem=char,
4> _Traits=std::char_traits<char>
4> ]
4> E:\Visual Studio 9.0\VC\include\streambuf(121) : see declaration of 'std::basic_streambuf<_Elem,_Traits>::sgetn'
4> with
4> [
4> _Elem=char,
4> _Traits=std::char_traits<char>
4> ]
谢谢!
【问题讨论】:
这是来自 VS 的输出。我的解决方案中有几个项目,它是编译项目 4 的输出。(有助于并行编译。) 【参考方案1】:如果您相信 Boost 不会传递超出范围的参数,则可以禁用警告。
微软为 C 库提出了一组新的“更安全”的函数,
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1225.pdf
并警告所有使用旧版本的人。
您也许还可以尝试更新的 Boost 库?最新的是 1.46.1
【讨论】:
除了编译器抱怨的函数不是 C,而是 C++,而且它非常安全(或者至少与使用 char* 的任何东西一样安全)。【参考方案2】:如果您的项目仅使用 Visual Studio 编译,您可以替换 _Sgetn_s 上对 sgetn 的调用(来自警告行)并复制初始调用的最后一个参数。这样您就可以将呼叫转换为安全呼叫。
或者您可以使用下面提供的补丁,它适用于 VC 8.0 及更高版本的 _Sgetn_s,但保留所有其他编译器的 sgetn。
Index: basic_binary_iprimitive.hpp
===================================================================
@@ -143,6 +143,11 @@
void
load_binary(void *address, std::size_t count);
;
+#if defined(_MSC_VER) && (_MSC_VER >= 1400) //VC 8.0 +
+# define BOOST_sgetn_safe( buf, count ) _Sgetn_s( buf, count, count )
+#else
+# define BOOST_sgetn_safe( buf, count ) sgetn( buf, count )
+#endif
template<class Archive, class Elem, class Tr>
inline void
@@ -157,6 +162,7 @@
);
std::streamsize s = static_cast<std::streamsize>(count / sizeof(Elem));
- std::streamsize scount = m_sb.sgetn(
+ std::streamsize scount = m_sb.BOOST_sgetn_safe(
static_cast<Elem *>(address),
s
);
@@ -173,7 +179,7 @@
// archive_exception(archive_exception::stream_error)
// );
Elem t;
- scount = m_sb.sgetn(& t, 1);
+ scount = m_sb.BOOST_sgetn_safe(& t, 1);
if(scount != 1)
boost::serialization::throw_exception(
archive_exception(archive_exception::input_stream_error)
@@ -181,6 +187,7 @@
std::memcpy(static_cast<char*>(address) + (count - s), &t, s);
+#undef BOOST_sgetn_safe
// namespace archive
// namespace boost
【讨论】:
【参考方案3】:Boost 文档承认有许多可以安全忽略的警告。通过在我的代码中添加以下内容,我从 Visual Studio 2008 的控制台中删除了恼人的警告消息:
#pragma warning(disable:4099)
【讨论】:
以上是关于提升序列化:可以安全地忽略警告?的主要内容,如果未能解决你的问题,请参考以下文章