C++ seekg无法正确处理4294967295字节的文件
我发现在VS2010中,当正好打开4294967295字节的文件时,seekg函数不能正常工作 我使用的是简单的代码: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
#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中固定,其中
#define _FPOSOFF(fp) ((long long)(fp))
如果你能做到的话,你最好升级到Visual C++ 2012。 此时有两个不太好的解决方案
这是一个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))