2011-11-19 5 views
1

방금 ​​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); 
} 

여기에 표시 할 수있는 유일한 방법은 sig1sig2 유형 char, sizeof(word) = 2sizeof(dword) = 4 모두 있다는 것입니다. 이 코드는 파일에 바이트를 두 번 작성한 다음 4 바이트 청크와 2 바이트 청크 두 개, 마지막으로 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에서는 -O2를 사용하여 gcc version 4.0.1 (Apple Inc. build 5490)을 사용하지만 다른 레벨은 아무 것도 변경하지 않았습니다.

+0

최소한의 독립 실행 형 테스트 케이스로 줄일 수 있습니까? (http://sscce.org 참조) –

+1

확실히 당신은'... (w)'대신에''char const * cw = reinterpret_cast (& w)'(끝에'&' 'cdw' /'dw'도 마찬가지입니까? 나는 충돌없이 달리는 것이 놀랍다. –

+0

나는 분명히 그랬다. 이제 완벽하게 작동합니다. 그 행동은 여전히 ​​이상합니다. –

답변

1

아담 로젠 필드가 그것을 찍었습니다. 당신은 w (단어)의 내용을 가져 와서 포인터로 취급하고 있었고 모든 지옥은 느슨해졌습니다. dw에 대해서도 마찬가지입니다.

그 후 임의의 쓰레기 ...

관련 문제