【发布时间】:2021-11-11 09:11:23
【问题描述】:
我们有类似下面的代码:
#include <sstream>
#include <iostream>
#include <fstream>
#include "boost/archive/binary_iarchive.hpp"
#include "boost/archive/binary_oarchive.hpp"
using namespace std;
class MetaData
{
public:
int old_GroupID;
int new_GroupID;
double newpos;
string newmessg;
template <typename Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar& old_GroupID;
ar& new_GroupID;
ar& newpos;
ar& newmessg;
}
};
void Serialization(const MetaData &object, ofstream &fileStream)
{
try
{
boost::archive::binary_oarchive oarch(fileStream);
oarch & object;
}
catch (boost::archive::archive_exception e)
{
cout << "boost::archive::archive_exception:exception while serialisation" << e.what() << endl;
}
catch (...)
{
cout << "unknow exception caught in Serialization" << endl;
}
}
void DeSerialization(const MetaData &object, stringstream &stringStreamer)
{
try
{
// This crashes instead of throwing
boost::archive::binary_iarchive iarch(stringStreamer);
iarch & object;
}
catch (boost::archive::archive_exception e)
{
cout << "boost::archive::archive_exception: exception" << e.what() << endl;
}
catch (...)
{
cout << "unknown exception caught" << endl;
}
}
int main()
{
string tempfilename = "/storage/serilazationfile.tmp";
{
ofstream OutputStream;
OutputStream.open(tempfilename, ios::out | ios::binary); //assuming file is opened
MetaData metadataobjectone;
metadataobjectone.old_GroupID = 1;
metadataobjectone.new_GroupID = 5;
metadataobjectone.newpos = 600.156;
metadataobjectone.newmessg = "A newmessage for object one";
Serialization(metadataobjectone, ofstream);
MetaData metadataobjecttwo;
metadataobjecttwo.old_GroupID = 2;
metadataobjecttwo.new_GroupID = 6;
metadataobjecttwo.newpos = 800.192;
metadataobjecttwo.newmessg = "A newmessage for object two";
Serialization(metadataobjecttwo, ofstream); //this seralize object , in the file should be corrupted like adding spaces or add unwanted data.
OutputStream.flush();
OutputStream.close();
}
stringstream stringStreamer;
ifstream InputStream;
InputStream.open(tempfilename, ios::in | ios::binary);
stringStreamer << InputStream.rdbuf();
stringStreamer.seekg(0, stringStreamer.end);
size_t FileSize = stringStreamer.tellg();
stringStreamer.seekg(0, stringStreamer.beg);
while (true)
{
MetaData object;//MetaData is a userdefined structure
DeSerialization(object, stringStreamer); //while deserializing 2nd oject(corrupted) exe will be crash in linux but it will not crash in windows.
//doing something with deserialized data
if (FileSize == stringStreamer.tellg())
{
break;
}
}
}
我们故意破坏serilazationfile.tmp(通过添加换行符或不需要的数据)以处理负面情况,例如文件偶然损坏或文件在实际环境中包含无效数据。
在 Windows 中,当反序列化损坏的文件时,会抛出一些异常并捕获“未知异常”,但在 Linux 中它会直接崩溃,即在 Linux 中它是无法捕获的。
那么这里的问题是什么,为什么在 Linux 中无法捕获这种情况?
使用 Boost 版本 1_58、x64bit ubuntu 18.05 和 x64bit Windows server 2016 进行测试。
我们得到了下面的调用栈:-
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007f36efef7921 in __GI_abort () at abort.c:79
#2 0x00007f36edd53b21 in Vmacore::PanicExit(char const*) () from /usr/lib/vmware/libvmacore.so
#3 0x00007f36edb1a75d in ?? () from /usr/lib/vmware/libvmacore.so
#4 0x00007f36f08f12ac in operator new(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007f36f0931c29 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007f36f0932afb in std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7 0x00007f36f0932bb4 in std::string::reserve(unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8 0x00007f36f0932f9c in std::string::append(unsigned long, char) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9 0x0000000002d97876 in boost::archive::basic_binary_iprimitive<boost::archive::binary_iarchive, char, std::char_traits<char> >::load(std::string&) ()
#10 0x0000000002d97a35 in boost::archive::basic_binary_iarchive<boost::archive::binary_iarchive>::init() ()
#11 0x00000000017a4ea3 in boost::archive::binary_iarchive_impl<boost::archive::binary_iarchive, char, std::char_traits<char> >::init (this=0x7f365d139570, flags=0)
at /usr/local/include/boost/archive/binary_iarchive_impl.hpp:68
#12 0x00000000017a4182 in boost::archive::binary_iarchive_impl<boost::archive::binary_iarchive, char, std::char_traits<char> >::binary_iarchive_impl (
this=0x7f365d139570, is=..., flags=0) at /usr/local/include/boost/archive/binary_iarchive_impl.hpp:97
#13 0x00000000017a3c93 in boost::archive::binary_iarchive::binary_iarchive (this=0x7f365d139570, is=..., flags=0)
at /usr/local/include/boost/archive/binary_iarchive.hpp:44
**#14 0x0000000002697c4a in CustmSerialization::Deserialization<MetaData*, std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> > > (
this=0x7f365d13a0dc, object=@0x7f365d1398b0: 0xd68, fileStream=...)
在CustmSerialization::Deserialization 中,我们有与上面示例类似的反序列化逻辑,并且我们有catch(...),但没有捕获到异常。
【问题讨论】:
-
@DevSolar 我已经提供了必要的细节,你现在可以检查一下吗。
-
这个例子还有很长的路要走。这个想法是任何人都可以复制您的示例,粘贴,编译,并准确查看您在问题中所说的内容。我添加了必要的包括
main()和一些适当的缩进。我还修复了 FileSize 缺少类型。代码仍然无法编译,因为someobjecttype没有声明,我完全不确定iarch & object;是否是正确的语法,但是我自己也没有使用过 Boost.Serialization。只是想向您展示如何编写一个有可能被回答的问题。 ;-) 关闭投票撤回 -
有一个简短的特定输入示例也会有所帮助。 -- 注意你可以
catch( const std::exception &e ) { std::cerr << e.what(); },或者catch( ... ) { boost::current_exception_diagnostic_information(); }#include "boost/exception/diagnostic_information.hpp"。