C++ Boost

序列化

归档异常


unregistered_class
invalid_signature
unsupported_version
unsupported_class_version
pointer_conflict
incompatible_native_format
array_size_too_short
input_stream_error
output_stream_error
invalid_class_name
unregistered_class
multiple_code_instantiation
xml_archive_parsing_error
xml_archive_tag_mismatch
xml_archive_tag_name_error
归档操作符可以抛出 boost::archive_exception 对象,应用程序可以捕获该对象。这些异常在文件 archive_exception.hpp basic_xml_archive.hpp 中定义。

namespace boost {
namespace archive {

class archive_exception  : public std::exception
{
public:
    typedef enum {
        unregistered_class,     // attempt to serialize a pointer of
                                // an unregistered class
        invalid_signature,      // first line of archive does not contain
                                // expected string
        unsupported_version,    // archive created with library version subsequent
                                // to this one
        pointer_conflict        // an attempt has been made to directly serialize
                                // an object after having already serialized the same
                                // object through a pointer.  Were this permitted, 
                                // the archive load would result in the creation
                                // of an extraneous object.
        incompatible_native_format, // attempt to read native binary format
                                // on incompatible platform
        array_size_too_short,   // array being loaded doesn't fit in array allocated
        input_stream_error      // error on stream input
        invalid_class_name,     // class name greater than the maximum permitted.
                                // most likely a corrupted archive or an attempt
                                // to insert virus via buffer overrun method.
        unregistered_cast,      // base - derived relationship not registered with 
                                // void_cast_register
        unsupported_class_version, // type saved with a version # greater than the 
                            // one used by the program.  This indicates that the program
                            // needs to be rebuilt.
        multiple_code_instantiation, // code for implementing serialization for some
                            // type has been instantiated in more than one module.
        output_stream_error     // error on stream output
    } exception_code;
    exception_code code;
    archive_exception(exception_code c) : code(c) {}
    virtual const char *what( ) const throw();
};

class xml_archive_exception : public virtual archive_exception
{
public:
    typedef enum {
        xml_archive_parsing_error,  // archive doesn't contain expected data 
	xml_archive_tag_mismatch,   // start/end tag in archive doesn't match program
        xml_archive_tag_name_error  // tag name contains invalid characters

    } exception_code;
    xml_archive_exception(exception_code c){}
    virtual const char *what( ) const throw();
};

} // archive
} // boost

unregistered_class

尝试通过指针序列化多态类,而没有注册它或将其与导出密钥关联。使用新归档时也可能出现这种情况,因为新归档的类名称尚未使用 BOOST_ARCHIVE_CUSTOM_ARCHIVE_TYPES 宏添加到系统中。

invalid_signature

归档以已知字符串开头。如果在打开归档时未找到此字符串,则假定此文件不是有效的归档,并且抛出此异常。

unsupported_version

此系统将当前库版本号记录到创建的所有归档中。请注意,这与应用程序使用的类的版本号完全无关。它指的是用于创建归档的序列化系统版本。此序列化系统的未来版本将能够识别以前(即此)系统下创建的归档,并相应地更改加载过程。因此,此序列化系统今后的增强不应使任何现有的归档文件过时。仅当较新的系统创建的归档与当前归档的格式不兼容时,才需要增加此版本号。

如果较旧的程序尝试读取格式已更改的较新归档,则会抛出此异常。

unsupported_class_version

尝试加载自该程序编写以来版本已升级的类。假设已为某个类指定了版本号 3,并且该程序已构建并发送给第三方。现在假设该类的定义已更改,版本号已升级到 4,并且已构建了新的归档。如果尝试使用原始程序加载这些新的归档,则会抛出此异常。

pointer_conflict

要理解此异常的含义,请考虑以下场景

template<class Archive>
void T::save(Archive &ar) const
{
    const A * aptr = &a;
    ar << aptr;          // save an instance of object of class A through a pointer
    ...
    ar << a;             // save an instance of an object of class A
    assert(aptr == &a);  // this must be true
}

template<class Archive>
void T::load(Archive &ar)
{
    A * aptr;
    ar >> aptr;          // create and initialize a new instance of class A
    ...
    ar >> a;             // restore state of on object of class A
    assert(aptr == &a);  // this won't be true
}
首先通过指针保存对象,然后直接保存。在按相同顺序重新加载时,我们首先创建一个新对象并在其中加载其数据。然后,我们将数据加载到另一个现有对象中。在保存时我们从一个对象开始,但在还原后我们有两个对象。在更真实的情况下,可能很难发现此错误。幸运的是,当创建归档时可以检测到这种情况。当发生这种情况时,会抛出此异常。

incompatible_native_format

该库当前支持 char 文本、宽 char 文本和原生二进制存档文件。在每个存档的开头,会写入一个签名来指示存档类型。当尝试读取以其他格式编写的存档时,会引发此异常。

array_size_too_short

已尝试读取大于数组大小的数组。这仅在存档已创建之后代码中数组的大小减小时才会发生。

input_stream_error
output_stream_error

流输入或输出期间发生错误。除了输入文件损坏或截断等常见情况外,还有若干有时会发生的不太明显的情况。

这包括尝试读取文件末尾的内容。文本文件需要在文件末尾终止换行符,该换行符将在调用存档析构函数时追加。确保在相同流上打开输入存档之前,会销毁该流上的输出存档。也就是说,要使用类似以下内容的内容,而不是


std::stringstream ss;
std::vector<V> v;
boost::archive::text_oarchive oa(ss);
oa << v;
boost::archive::text_iarchive ia(ss);
ia >> v;
使用

std::stringstream ss;
std::vector<V> v;
{
    boost::archive::text_oarchive oa(ss);
    oa << v;
}
{
    boost::archive::text_iarchive ia(ss);
    ia >> v;
}

另一种情况是传递未初始化的数据。通常,当传递未初始化的数据时,序列化库的行为是未定义的。如果可以检测到,它将在调试生成中调用断言。否则,根据存档的类型,它可能会顺利通过,也可能导致存档中包含意外数据。这进而可能导致抛出此异常。

invalid_class_name

类名长度大于允许的最大长度。最可能的原因是存档损坏或尝试通过缓冲区溢出方法插入病毒。

unregistered_cast

为了支持在运行时转换基础类和派生类的指针,系统会维护合法转换的集合。通常,此集合的维护不需要库用户执行任何显式操作。但是,在特殊情况下,可能必须显式执行此操作并且可能会被忽视。这在运行时转换中进行了描述。如果尝试转换两个尚未注册其关系的指针,则会引发此异常。

multiple_code_instantiation

当检测到同种类型序列化已实例化多次时,会引发此异常。当主干和一个或多个 DLL 中实例化序列化代码时,可能会发生这种情况。

xml_archive_parsing_error

序列化过程生成的 XML 紧紧耦合到 C++ 类结构、对象之间的关系和序列化规范。如果这些方面以某种方式不同步,则 XML 可能无法映射到加载序列化,并且可能会引发此异常。这可能由于以下某个原因而发生

xml_archive_tag_mismatch

如果 XML 元素的开始或结束标记与程序中为对象指定的名称不匹配,则会引发此异常。

xml_archive_tag_name_error

如果标签名称包含无效字符,则会引发此异常。XML 标签的有效字符是:大写和小写字母、数字以及以下标点符号: .(句点)、 _(下划线)、 :(冒号) 和 -(连字符)。

© Copyright 罗伯特雷米 2002-2004。按 Boost 软件许可证版本 1.0 分发。(请参阅随附文件 LICENSE_1_0.txt 或复制到 https://boost.ac.cn/LICENSE_1_0.txt)