【问题标题】:std::ofstream repeats and looses written data for no reasonstd::ofstream 无缘无故地重复和丢失写入的数据
【发布时间】:2011-11-19 22:40:07
【问题描述】:

我刚刚目睹了std::ofstream::write 方法的一种异常怪异的行为。我正在编写自己的 Windows BMP 文件格式处理方法,其中包括将位图保存到文件中——作为介绍。这是一个负责写入位图文件头的子程序,参考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都是charsizeof(word) = 2sizeof(dword) = 4类型。此代码应导致两次将一个字节写入文件,然后是一个四字节块,两个两字节块,最后是一个四字节块。

看一下结果的十六进制转储(后面还有一些东西,但忽略它们):

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

sig1sig2 被打印两次,在开头和出于某种奇怪的原因也在第 11 和第 12 字节处有一个正确的值,实际上是 BM。我不承认这一行中的其他价值观。但是看看如果我在每个 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 字节序列。有人可以帮我找出原因吗?它是编译时的错误吗?我在带有 -O2 的 Mac OS X Leopard 上使用 gcc version 4.0.1 (Apple Inc. build 5490),但其他级别没有任何改变。

【问题讨论】:

  • 你能把它简化为一个最小的独立测试用例吗? (见sscce.org
  • 您的意思是写char const* cw = reinterpret_cast&lt;char&gt;(&amp;w)(注意末尾的&amp; 运算符)而不是...(w),同样是cdw/dw?我很惊讶它运行时没有崩溃。
  • 我确实做到了。现在它完美无缺。不过,这种行为仍然很奇怪。

标签: c++ file ofstream


【解决方案1】:

亚当·罗森菲尔德成功了。您正在获取 w (一个单词)的内容并将其视为指针......然后一切都乱了套。 dw 也是一样。

之后的随机垃圾......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-04
    • 1970-01-01
    • 2019-11-02
    • 2020-03-01
    • 2019-10-24
    • 2011-07-02
    • 1970-01-01
    • 2013-08-11
    相关资源
    最近更新 更多