c++ - 文件解析中奇怪的对象序列化问题

标签 c++ serialization file-io

我在对象序列化方面遇到了一个奇怪的问题。 在文件文档中它声明如下

The lead in starts with a 4-byte tag that identifies a TDMS segment ("TDSm"). The next four bytes are used as a bit mask in order to indicate what kind of data the segment contains. This bit mask is referred to as ToC (Table of Contents). Any combination of the following flags can be encoded in the ToC: The next four bytes contain a version number (32-bit unsigned integer), which specifies the oldest TDMS revision a segment complies with. At the time of this writing, the version number is 4713. The only previous version of TDMS has number 4712. The next eight bytes (64-bit unsigned integer) describe the length of the remaining segment (overall length of the segment minus length of the lead in). If further segments are appended to the file, this number can be used to locate the starting point of the following segment. If an application encountered a severe problem while writing to a TDMS file (crash, power outage), all bytes of this integer can be 0xFF. This can only happen to the last segment in a file. The last eight bytes (64-bit unsigned integer) describe the overall length of the meta information in the segment. This information is used for random access to the raw data. If the segment contains no meta data at all (properties, index information, object list), this value will be 0.

所以我实现为

class TDMsLEADIN {
public:
    char   Signature[4];    //TDSm
    __int32     Toc;
    unsigned __int32     vernum;
    unsigned __int64  nextSegmentOff;
    unsigned __int64  rawDataOff;
};
fread(&leadin,sizeof(TDMsLEADIN),1,f);

然后我得到了预期的 signature="TDsm", TOc=6, vernum=4712。 nextSegmentOff=833223655424,rawDataOff=8589934592 但预计 nextSegmentOff 和 rawDataOff=194

然后我将类(class)分成两部分,分别阅读两部分

class TDMsLEADIN {
public:
    char   Signature[4];    //TDSm
    __int32     Toc;
    unsigned __int32     vernum;

};
class TDMsLeadINend{
public:
    unsigned __int64 nextSegmentOff;
    unsigned __int64 rawDataOff;
};
    fread(&leadin,sizeof(TDMsLEADIN),1,f);
    fread(&leadin2,sizeof(TDMsLeadINend),1,f);

然后我得到了预期的 nextSegmentOff ,rawDataOff=194。 我的问题是原始代码有什么问题?为什么当我把它分成两部分时它会起作用?我尝试使用 unsigned long long 而不是 unsigned __int64,但结果仍然相同。 这很奇怪。

谢谢

最佳答案

您似乎只是直接在结构中读写二进制数据。

通常编译器会为了性能对齐结构数据,所以当它是单个结构时,在 vernumnextSegmentOff 之间有一个隐藏的 32 位填充以对齐 nextSegmentOff 。当它被分成两个结构时,就没有这样的额外填充,您正在将四个字节的填充和四个字节的实际数据读入 nextSegmentOff

您可以通过将 sizeof(TDMsLEADIN [second version]) + sizeof(TDMsLeadINend)sizeof(TDMsLEADIN [first version]) 进行比较来测试这一点

序列化数据的标准方法是单独序列化每个基础部分,而不是依赖于类或结构的布局,因为编译器可能会更改布局,恕不另行通知。

关于c++ - 文件解析中奇怪的对象序列化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3150844/

相关文章:

java - 如何判断哪个字段失败Gson序列化

c++ - 如何从函数中获取一 block 内存并将其写入文件?

c - 我做错了什么?下面的代码不会将结构化数据的最后一条记录从 .dat 文件复制到 C 中的另一个 .dat 文件

c++ - 什么是 Matlabs `fread(fp, 1, ' int3 2')` 和 fread(fp, n, 'uchar' ) 的 C++ 翻译

c++ - 使用 "if"或 "switch"设置变量类型

java - 有没有办法使用 jersey 配置部分或完全序列化为 json?

ruby-on-rails - postgres_ext/serializers 帮助...看起来很简单,但无法按照描述进行任何操作

c++ - 在 C MexFunction 中使用 Besselk 函数

c++ - 无法理解 "list<int>::iterator i;"

c++ - 如何对各向异性过滤支持进行硬件级别检查?