seekg无法正确处理4294967295字节的文件

Rus*_*sty 10 c++ visual-studio-2010 seekg

我发现在VS2010中,当打开正好为4294967295字节的文件时,seekg函数无法正常工作.

我正在使用简单的代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

与文件4294967294和4294967296相同的代码工作没有任何问题.

有人知道这个问题的解决方案吗?

更新:

看起来这个问题就在这里:

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

确切地说

_FPOSOFF(_Fpos)
Run Code Online (Sandbox Code Playgroud)

哪里

#define _FPOSOFF(fp) ((long)(fp))
Run Code Online (Sandbox Code Playgroud)

所以它需要4294967295并将其转换为-1!

换句话说,这样的代码将失败

//returns -1, even if sizeof(fpos_t)=8
fpos_t pos = _FPOSOFF(4294967295);
Run Code Online (Sandbox Code Playgroud)

_Myoff,_Fpos,streamoffset是64位

如果所有类型都是64位,他们为什么要进行此转换!?我不知道 ))

Jas*_*onD 7

在内部,流实现有一个const'_BADOFF',它等于0xffffffff,当搜索失败时返回它.在这种情况下,搜索成功,但搜索的返回值等于失败代码,这导致流包装器错误地设置其失败代码.

_BADOFF定义为64位类型,它刚被赋予了一个愚蠢的值.

作为一种解决方法,您可以寻找1字节短路,然后读取一个字节.

file.seekg(-1, std::ios::end);
char temp; file >> temp;
Run Code Online (Sandbox Code Playgroud)

但请注意,此错误将在任何时候显示特定的文件偏移量,因此如果您在其中寻找随机位置,它仍可能是较大文件的问题.例如,如果您的文件大一个字节,则此-1搜索将失败,因此这不是一般解决方案.

OP已经扩展了他们的问题,所以我会扩展我的答案.是的,在比较之前使用不安全的转换来转换搜索值.这似乎不会影响在文件中超出该点的搜索能力,因为它仅用于与错误值进行比较 - 流中仍然具有正确的偏移量.然而,它似乎确实是_BADOFF首先是可疑的根本原因,因为_BADOFF在源中被设置为'-1',并且将遭受相同的转换,截断为0xffffffff.

因此libs的修复可能是修复强制转换(假设没有其他副作用),但为了解决问题,你只需要避免寻找底部32位的位置已设定.从我能看到的情况来看,它将寻求超越这一点.

  • WTF(真是太棒了) (4认同)
  • 他的意思是胜利,不要称他为雪莉 (3认同)

Jam*_*lis 5

这确实是Visual C++ 2010中的一个错误.两年前在Microsoft Connect上报告过: " std::fstream即使在x64平台上也使用32位int作为pos_type"(错误的标题不正确;症状实际上是由这个错误引起的in _FPOSOFF).

此错误在Visual C++ 2012中得到修复,其中_FPOSOFF定义为:

#define _FPOSOFF(fp)  ((long long)(fp))
Run Code Online (Sandbox Code Playgroud)

如果能够这样做,建议您升级到Visual C++ 2012.