C++ 按字段读取结构并将结构直接写入流

标签 c++ serialization deserialization abi

我正在使用 C++ 和 Visual Studio 2008。假设我有这样的结构:

    struct StructOfInts
    { 
        int a;
        int b;
        int c; 
    };

这应该像这样读取和写入:

    void Read( std::istream& is, StructOfInts& myStruct  )
    {
        is.read( (char*)&myStruct.a, sizeof myStruct.a );
        is.read( (char*)&myStruct.b, sizeof myStruct.b );
        is.read( (char*)&myStruct.c, sizeof myStruct.c );
    }
    void Write( std::ostream& os, StructOfInts& myStuct )
    {
        os.write( (char*)&myStruct, sizeof myStruct );
    }

在读取或写入文件时,上述代码是否会导致某种内存损坏?我所说的内存损坏是指读入的值不正确。我正在尝试确定正在读入的 -1.#QNB 值的来源,并且想知道这是否可能是原因。 另外,如果我使用 pragma pack 打包结构会有什么不同吗?

最佳答案

是的,由于 struct 字段之间可能存在填充,您的代码可能导致读入无效值。让我们使用 struct StructOfInts 的示例,并想象编译器在字段之间插入一些填充,如下所示:

byte  | 0 1 2 3 | 4 5     | 6 7 8 9 | 10 11 12 13
value | field a | padding | field b | field c

然后,当您将结构写入流时,您可能会得到类似的结果

byte | 0  1  2  3   | 4   5   | 6  7  8  9   | 10 11 12 13
char | \0 \0 \0 'a' | '?' '?' | \0 \0 \0 'b' | \0 \0 \0 'c'

如果字段(分别)包含值(int)'a'、(int)'b'、(int)'c'

然后当您读回这些值时,它看起来像

myStruct->a = int version of \0 \0 \0 'a'
myStruct->b = int version of '?' '?' \0 \0
myStruct->c = int version of \0 'b' \0 \0

这显然不是你想要的。

在搜索了#pragma pack之后,看起来它会对这种情况有所帮助。编译器不会插入填充(尽管它是实现定义的...),因此这些值(很可能)会被正确读取和写入。

此外,另一件事:如果您在一个系统(计算机/操作系统/编译器)上进行写入,然后在另一个系统中读取数据,那么字节序问题也可能会导致问题。

关于C++ 按字段读取结构并将结构直接写入流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17454201/

相关文章:

c++ - 不同 header 中的类不能相互识别?

java - 包装结构的JSON与扁平化结构的pojo之间的转换

Python 序列化(到 JSON)问题

compact-framework - 为紧凑框架预编译 protobuf-net 类型模型

json - 忽略Gson反序列化中的一些嵌套项

c++ - [C++] 在此代码之前不存在的析构函数中抛出的内存错误。尝试制作一个新的动态数组并填充它

javascript - 使用 QJSEngine 在 Qt 中执行 Javascript 的速度

serialization - 基于它与 Jackson 或 Gson 实现的一个接口(interface)序列化类

c++ - 从 json 文件构建 boost 属性树性能很差?

c++ - 如何将二进制格式的 C++ 对象的 std::vector 保存到磁盘?