2013-07-03 140 views
2

我使用C++,与2008年的Visual Studio说我有一个结构,像这样:C++阅读结构的领域,直接写入结构到流

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值的来源,并且想知道这是否可能是原因。 另外,如果我使用杂注包打包结构,是否有区别?

+2

没有使用>>操作符的任何特定原因? – Borgleader

+0

没有特别的理由。这就是我正在使用的(非常古老的)代码库是如何保持一致性的。 – kushaldsouza

+0

我认为问题出现在这一行:'os.write((char *)&myStruct,sizeof myStruct);'。尝试按元素写入“ostream”元素。因为如果你在64位机器上,可能会有填充,因为“sizeof(int)”将是32位。 –

回答

1

快速的方法来测试这种情况下是:

static_assert(sizeof(StructOfInts) == (3 * sizeof(int)), "size mismatch"); 

的最佳方式来完成这个(IMO)是使用对称形式:序列字段逐场,然后也反序列化场逐领域。

简而言之,依赖于您的实施使用的行为是依赖于目标体系结构的ABI,而不是标准(BAD)。因此,这可能导致“腐败”。

结构的大小可能因ABI而异,并且整数大小甚至字节顺序可能会有所不同,从而导致“腐败”。填充和对齐也由ABI指定。

因此,固定宽度类型,显式字节顺序和字段按字段对称序列化通常是您所需要的。

+0

感谢您的回答。我尝试了静态断言(好主意btw),不幸的是(或者幸运)它没有触发。你认为这意味着我的特殊情况下的阅读/写作会正确吗?我面临的问题发生非常不一致,可能会或可能不会与此有关。 – kushaldsouza

+0

@ k9ty如果你只在一个体系结构上运行时读取和写入这些文件(例如Windows,32位),那么问题将在别处。你的程序只是告诉它做POD的字节拷贝,并且大小一致。如果您在多个平台/体系结构上运行它,则允许序列化表示形式不同(即sizeof(int)可能甚至不相同)。 – justin

2

是的,您的代码可能导致无效值被读入,因为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,它看起来像它会帮助这种情况。编译器不会插入填充(尽管它实现已定义...),所以这些值(很可能)会被正确读取和写入。另外,还有一件事:如果你在一个系统(计算机/操作系统/编译器)上编写代码,然后在另一个系统中读取数据,那么字节顺序问题也可能导致问题。

+0

太棒了,谢谢你的回答。 – kushaldsouza

+0

@ k9ty没问题:) – feralin