방금 std::ofstream::write
메서드의 광기가 넘치는 동작을 목격했습니다. 나는 비트 맵을 파일로 저장하는 것을 포함하여 윈도우의 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);
}
여기에 표시 할 수있는 유일한 방법은 sig1
및 sig2
유형 char
, sizeof(word) = 2
및 sizeof(dword) = 4
모두 있다는 것입니다. 이 코드는 파일에 바이트를 두 번 작성한 다음 4 바이트 청크와 2 바이트 청크 두 개, 마지막으로 4 바이트 청크를 생성해야합니다. 결과의 진수 덤프에서
를 적어 보면 (이 따라 몇 가지도 있지만, 그들을 무시) :
00000000 42 4d 42 4d 00 00 00 05 00 05 42 4d 00 00 28 00 |BMBM......BM..(.|
sig1
및 sig2
실제로 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에서는 -O2를 사용하여 gcc version 4.0.1 (Apple Inc. build 5490)
을 사용하지만 다른 레벨은 아무 것도 변경하지 않았습니다.
최소한의 독립 실행 형 테스트 케이스로 줄일 수 있습니까? (http://sscce.org 참조) –
확실히 당신은'... (w)'대신에''char const * cw = reinterpret_cast (& w)'(끝에'&' 'cdw' /'dw'도 마찬가지입니까? 나는 충돌없이 달리는 것이 놀랍다. –
나는 분명히 그랬다. 이제 완벽하게 작동합니다. 그 행동은 여전히 이상합니다. –