C 语言fseek. ftell调用失败(fseek返回非零值,ftell返回-1)
太长不看版
fseek调用失败,返回非零值,是因为传入的参数超过了文件尾,或者文件大于2G,需要使用fseek的64 bit版本_fseeki64.
ftell调用失败,返回-1,唯一一次遇到是因为文件大于2G,需要使用ftell的64bit版本,_ftelli64.
BUG重现
size_t offset = 0;
size_t file_data_size = 0,pos_start = 0,pos_end = 0;
unsigned char * buffer = NULL;
pos_start = ftell(fp);//此处正常
fseek(fp, 0L, SEEK_END);
pos_end = ftell(fp);//此处返回一个很大的值
file_data_size = pos_end - pos_start;
buffer = new unsigned char[file_data_size];
错误分析
- pos_start和pos_end此处应该是long。
- 文件大小超过了2G,应该使用64 bit的版本。
修改后
size_t offset = 0;
__int64 file_data_size = 0,pos_start = 0,pos_end = 0;
unsigned char * buffer = NULL;
pos_start = 0;
rnt_value = _fseeki64(fp, 0L, SEEK_END);
pos_end = _ftelli64(fp);
if (pos_end != -1 && pos_start != -1)
{
file_data_size = pos_end - pos_start;
}
else
{
std::cout << "error: fseek error\t" << __FILE__ << __LINE__ << std::endl;
return false;
}
buffer = new unsigned char[file_data_size];
_fseeki64(fp, pos_start, SEEK_SET);
fread(buffer, sizeof(unsigned char), file_data_size, fp);
修改分析
- pos应该定义为int64,而不是其他任何类型。
- 使用fseek和ftell的64 bit版本。
fseek与ftell
参考:C标准库,P249, P250