2013-07-03 101 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