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位,他们为什么要进行此转换!?我不知道 ))
在内部,流实现有一个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位的位置已设定.从我能看到的情况来看,它将寻求超越这一点.
这确实是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.
| 归档时间: |
|
| 查看次数: |
2333 次 |
| 最近记录: |