【发布时间】:2017-05-02 07:34:15
【问题描述】:
在将项目从 vs2008 迁移到 vs2015 时,我陷入了看起来像是 VS2015 libc 中的错误。 问题是在对位置 X 执行 fseek 操作后,fread 从 X+10 开始读取数据。
没有引发错误,fseek 操作返回参与位置后的 ftell 调用,但 fread 未从参与位置开始。而且,它依赖于之前的 fseek/fread 操作。
使用 VS2008(32 或 64 位)运行时不会出现此问题,但使用 VS2015(32 或 64 位)运行时会出现此问题。
提前感谢您的任何想法!
二进制文件可用here。 示例代码:
#include <fstream>
#include <iostream>
#include <iomanip>
#include <windows.h>
bool foo(FILE *f, unsigned char *buffer, int seek_to, int read_bytes)
{
size_t res = 0;
std::cout << "\tSeek to " << seek_to << std::endl;
// issue present if using fseek or _fseeki64
if (fseek(f, seek_to, SEEK_SET) != 0)
{
std::cout << "\tFAILED" << std::endl;
return false;
}
std::cout << "\tRead " << read_bytes << " bytes" << std::endl;
if ((res = fread(buffer, 1, read_bytes, f)) != read_bytes)
{
std::cout << "\tFAILED, " << res << "bytes readen" << std::endl;
return false;
}
return true;
}
// issue is present in 32 and 64bits of VS2015 update 3
int main(int argc, char **argv)
{
// open the AVC binary file
FILE *favc = fopen(argv[1], "rb");
// big buffer
unsigned char *buffer = new unsigned char[1024*1024];
// step 1, seek and read
std::cout << "Step 1" << std::endl;
foo(favc, buffer, 35026374, 7730);
std::cout << "Step 2" << std::endl;
foo(favc, buffer, 35030470, 8192);
// failing reading, buffer should start with 00 00 00 01 09
std::cout << "Step 3 - where all failed" << std::endl;
foo(favc, buffer, 35034577, 16428);
std::cout << "Buffer: '";
for (size_t i = 0; i < 5; ++i) std::cout << std::hex << std::setw(2) << std::setfill('0') << (unsigned int)buffer[i];
std::cout << "'" << std::endl;
unsigned int v = *((unsigned int*)(buffer+1));
if (v != 0x09010000) std::cout << "ISSUE DETECTED" << std::endl;
return 0;
}
【问题讨论】:
-
请注意: - 如果使用 fread_s/fopen_s 或 _open/_lseek/_read 函数,这也会出现
-
如果使用 _open、_read 和 _lseek,则不存在问题。看起来就像 vs2015 上 fopen 中的缓冲错误
-
VS2017中也有....
-
使用 setvbuf 调整缓冲区大小也会更改问题位置。似乎真的是缓冲的错误。
-
在 Windows 10 上运行时不存在问题... :(
标签: visual-studio-2015 fread fseek