Search code examples
c++visual-studio-2010seekg

seekg cannot handle file of 4294967295 bytes properly


I found that in VS2010, seekg function does not work properly when file of exactly 4294967295 bytes is opened.

I'm using simple code:

#include <iostream>
#include <fstream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    std::ifstream file;

    // cmd: fsutil file createnew tmp.txt 4294967295
    file.open(L"c:/tmp.txt", ifstream::in | ifstream::binary);

    if(!file.is_open())
        return -1;

    file.seekg(0, std::ios::end);

    auto state = file.rdstate();

    // this condition shoots only when size of the file is equal to 4294967295
    if((state & ifstream::failbit)==ifstream::failbit)
    {
        std::cout << "seekg failed";
    }

    // after seekg failed, tellg returns 0
    std::streampos endPos = file.tellg();

    return 0;
}

Same code with files of 4294967294 and 4294967296 is working without any problems.

Does someone know a solution to this problem?

Update:

It looks like that problem lies here:

template<class _Statetype>
class fpos
{
 __CLR_OR_THIS_CALL operator streamoff() const
 { // return offset
 return ((streamoff)(_Myoff + _FPOSOFF(_Fpos)));
 }
}

exactly at

_FPOSOFF(_Fpos)

where

#define _FPOSOFF(fp) ((long)(fp))

So it takes 4294967295 and converts it to -1 !

In other words speaking, such code will fail

//returns -1, even if sizeof(fpos_t)=8
fpos_t pos = _FPOSOFF(4294967295);

_Myoff, _Fpos, streamoffset are 64bit

Why they do this conversion if all types are 64 bit!? I have no idea ))


Solution

  • This is indeed a bug in Visual C++ 2010. It was reported on Microsoft Connect two years ago: "std::fstream use 32-bit int as pos_type even on x64 platform" (the title of the bug is incorrect; the symptoms were actually caused by this bug in _FPOSOFF).

    This bug is fixed in Visual C++ 2012, wherein _FPOSOFF is defined as:

    #define _FPOSOFF(fp)  ((long long)(fp))
    

    You would be well advised to upgrade to Visual C++ 2012 if you are able to do so.