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

C++ seekg无法正确处理4294967295字节的文件,c++,visual-studio-2010,seekg,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

我发现在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;
}
在哪里

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

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

//returns -1, even if sizeof(fpos_t)=8
fpos_t pos = _FPOSOFF(4294967295);
_Myoff、_fpo、streamoffset为64位


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

在内部,流实现有一个常量“\u BADOFF”,它等于0xffffffff,在寻道失败时返回。在这种情况下,seek成功,但seek返回的值等于失败代码,这导致流包装器错误地设置其失败代码

_BADOFF被定义为64位类型,它只是被分配了一个愚蠢的值

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

file.seekg(-1, std::ios::end);
char temp; file >> temp;
但是请注意,这个错误会在任何时候出现,特定的文件偏移量被搜索到,所以如果你在较大的文件中搜索到随机的位置,它仍然可能是一个问题。例如,如果文件大一个字节,那么-1搜索将失败,因此这不是一个通用的解决方案

OP已经扩展了他们的问题,所以我将扩展我的答案。是的,在比较之前使用不安全的转换转换查找值。这似乎不会影响查找文件中超出该点的能力,因为它仅用于与错误值进行比较-流中仍然有正确的偏移量。然而,这似乎确实是_BADOFF最初可疑的根本原因,因为_BADOFF在源代码中被设置为“-1”,并且将经历相同的转换,截断为0xFFFFFF


因此,LIB的修复可能是修复强制转换(假设这样做没有其他副作用),但为了解决这个问题,您只需避免寻找设置底部32位的位置。从C++中可以看出,这是一个bug,VisualC++ 2010中的bug。这是两年前在Microsoft Connect上报告的:(错误的标题不正确;症状实际上是由
\u FPOSOFF
中的此错误引起的)

此bug在Visual C++ 2012中固定,其中>FPOOXOF/<代码>定义为:

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

如果你能做到的话,你最好升级到Visual C++ 2012。

此时有两个不太好的解决方案

  • 在stdio.h中进行修复

    #定义_FPOSOFF(fp)((long-long)(fp))

  • 移到VS2012(这也是令人伤心的)


    这是一个bug,在Visual Studio 2012中已修复:_FPOSOFF现在强制转换为long long,因此>避免了截断詹姆斯·麦克内利斯


  • 注:4294967295为0xffffffff。可能有一些32位代码正在崩溃。考虑到4294967295与-1是相同的位模式,如果这是运行时的错误,我也不会感到惊讶。恐怕我没有解决办法……这是一个bug,在Visual Studio 2012中已修复:
    \u FPOSOFF
    现在强制转换为
    long
    ,从而避免了截断。WTF(多么可怕的失败)太棒了?雪莉你是说“糟糕”?他是指胜利,不要叫他雪莉我更新了我的问题,问题在于转换成long@user1897425当前位置请不要在事后改变问题。这是您发布的问题的答案-如果您有新问题,请发布新问题。您的编辑应该回滚,并且此答案标记为已接受。谢谢,我还打算在VS2012上检查它,但移动到另一个IDE并不总是那么容易。
    //returns -1, even if sizeof(fpos_t)=8
    fpos_t pos = _FPOSOFF(4294967295);
    
    file.seekg(-1, std::ios::end);
    char temp; file >> temp;
    
    #define _FPOSOFF(fp)  ((long long)(fp))