2011-11-19 42 views
1

我剛剛目睹了std::ofstream::write方法的瘋狂bizzare行爲。我正在編寫自己的Windows'BMP文件格式處理,其中包括將位圖保存到文件 - 這是一個介紹。給定參考std::ofstream對象,這是一個負責編寫位圖文件頭的子例程。std :: ofstream重複並丟失書面數據無故

void 
BitmapFileManager::FileHeader::save(std::ofstream& fout) const 
{ 
    word  w; 
    dword  dw; 
    char const* cw = reinterpret_cast<char*>(w); 
    char const* cdw = reinterpret_cast<char*>(dw); 
    uint const sw = sizeof(w); 
    uint const sdw = sizeof(dw); 

    fout.write(&sig1, sizeof(sig1)); 
    fout.write(&sig2, sizeof(sig2)); 
    dw = toLittleEndian(size);   fout.write(cdw, sdw); 
    w = toLittleEndian(reserved1); fout.write(cw , sw); 
    w = toLittleEndian(reserved2); fout.write(cw , sw); 
    dw = toLittleEndian(pixelsOffset); fout.write(cdw, sdw); 
} 

在這裏紀念的唯一的事情就是sig1sig2都是char類型,sizeof(word) = 2sizeof(dword) = 4的。該代碼應該導致兩次將一個字節寫入文件,然後是四個字節的塊,兩個兩個字節的塊,最後是四個字節的塊。

採取看看結果的十六進制轉儲(也有一些事情,跟着,卻忽略了他們):

00000000 42 4d 42 4d 00 00 00 05 00 05 42 4d 00 00 28 00 |BMBM......BM..(.| 

sig1sig2印刷兩次,這實際上是B和一個合適的值M,一開始也有一些奇怪的原因,在第11和第12字節。我不承認這一行中的其他價值。但是,看看,如果我每write之間增加一個調試字節會發生什麼:

void 
BitmapFileManager::FileHeader::save(std::ofstream& fout) const 
{ 
    word  w; 
    dword  dw; 
    char const* cw = reinterpret_cast<char*>(w); 
    char const* cdw = reinterpret_cast<char*>(dw); 
    uint const sw = sizeof(w); 
    uint const sdw = sizeof(dw); 

    char nil = '*'; 
    fout.write(&sig1, sizeof(sig1)); 
    fout.write(&nil, sizeof(nil)); 
    fout.write(&sig2, sizeof(sig2)); 
    fout.write(&nil, sizeof(nil)); 
    dw = toLittleEndian(size);   fout.write(cdw, sdw); 
    fout.write(&nil, sizeof(nil)); 
    w = toLittleEndian(reserved1); fout.write(cw , sw); 
    fout.write(&nil, sizeof(nil)); 
    w = toLittleEndian(reserved2); fout.write(cw , sw); 
    fout.write(&nil, sizeof(nil)); 
    dw = toLittleEndian(pixelsOffset); fout.write(cdw, sdw); 
    fout.write(&nil, sizeof(nil)); 
} 

十六進制轉儲則

00000000 42 2a 4d 2a 6c 3b 78 a0 2a 00 05 2a 00 05 2a 6c |B*M*l;x?*..*..*l| 
00000010 3b 78 a0 2a 28 00 00 00 28 00 00 00 28 00 00 00 |;x?*(...(...(...| 

看起來這是完全正常的。沒有重複,並且*按照它應該將字符串分成1-1-4-2-2-4字節的序列。有人能幫我找到這個的原因嗎?這是編譯錯誤嗎?我在Mac OS X Leopard上使用gcc version 4.0.1 (Apple Inc. build 5490),但是其他級別沒有任何改變。

+0

你可以減少到最小的獨立測試案例嗎? (見http://sscce.org) –

+1

當然,你的意思是寫'char const * cw = reinterpret_cast (&w)'(注意最後的'&'運算符)而不是'...(w)',同樣對於'cdw' /'dw'?我很驚訝,運行沒有崩潰。 –

+0

我當然做到了。現在它完美地工作。但行爲仍然很奇怪。 –

回答

1

亞當羅森菲爾德釘了它。你把一個w(一個單詞)的內容作爲一個指針來處理......然後所有的東西都打破了。對於dw同樣的事情。

之後的隨機垃圾...