一个奇怪的fread后偏移量不正确的问题

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <Windows.h>

//encrypt data
void EncryptBlock(unsigned char*& blockdata, size_t n)
{

}

//encrypt file
bool EncryptFile(const char* path, size_t blocksize)
{
	FILE* fp = NULL;
	auto erno = fopen_s(&fp, path, "rb+");
	if (erno != 0)
	{
		printf("openfile:[%s] fail!!, errno=%d\n", path, erno);
		return false;
	}

	//get file size
	_fseeki64(fp, 0, SEEK_END);
	int64_t filesize = _ftelli64(fp);
	_fseeki64(fp, 0, SEEK_SET);
	printf("filesize:%lld, %lldmb\n", filesize, filesize / (1024 * 1024));

	int64_t processed = 0;
	//buffer
	unsigned char* blockdata = new  unsigned char[blocksize];
	while (1)
	{
		int64_t currpos = _ftelli64(fp);
		//printf("curr:%lld, size=%lldmb\n", currpos, currpos / (1024 * 1024));

		//read and set offset 
		size_t readsize = fread(blockdata, 1, blocksize, fp);
		if (0 == readsize)
		{
			break;
		}
		int64_t currpos2 = _ftelli64(fp);
		if (currpos + readsize != currpos2)
		{
			printf("offset incorrect\n");
			break;
		}
		_fseeki64(fp, -1 * readsize, SEEK_CUR);

		//encrypt
		EncryptBlock(blockdata, readsize);

		//write
		size_t writesize = fwrite(blockdata, 1, readsize, fp);
		if (writesize != readsize)
		{
			printf("write:writesize=%llu, readsize=%llu, warning!!!!!!!!!!!\n", writesize, readsize);
		}
		processed += writesize;
		//_fseeki64(fp, 1 * processed, SEEK_SET);
		//fflush(fp);

		if (readsize != blocksize)
		{
			printf("readsize=%llu, block=%llu, break[processd:%llu]\n", readsize, blocksize, processed);
			break;
		}
	}
	delete[] blockdata;
	fclose(fp);

	//error
	if (processed != filesize)
	{
		printf("processed(%lld) != filesize(%lld), warning!!!!!!!!!!!\n", processed, filesize);
		return false;
	}
	else
	{
		return true;
	}
}


int main(int argc, char *argv[])
{
	auto tv1 = GetTickCount64();
	auto suc = EncryptFile("d:\\soft.msi", 1024 * 102);
	auto tv2 = GetTickCount64();

	auto used = (tv2 - tv1);
	printf("encrypt:%s, cost:%llums\n", suc ? " succ" : " fail", used);
	getchar();
	return 0;
}

功能很简单,读取一个文件,每次读取一块,加密后写回原位置,直到整个文件完成加密。
当使用EncryptFile("d:\\soft.msi", 1024 * 1024)时运行良好,但是当时手一抖,变成了EncryptFile("d:\\soft.msi", 1024 * 102)报了错。
经过调试之后,发现错误情况如下
fread
通过查询fwriteftell确认文件指针的偏移量,在第二次fread之前确实符合文档说明的。
但是第二次fread之后,会发现偏移量对不上。查询fread发现和文档不一致了。
此时完全不知道应该怎么处理。
后续在LINUX下对上述代码进行验证,发现也是一样的情况。基本可以确定是代码写错了。
然后在stackoverflow上发帖询问,在搞清stackoverflow各种规则后,非常幸运的很快就有人指出了错误的原因。
fopen函数的问题
stackoverflow.fopen
然后再去microsoft.doc.fopen上查找,也是明确说明了调用的规则。
msdn.fopen
上述代码在fwrite之后,调用fflush即可获得预期的行为

posted on 2021-07-08 18:00  tang_god  阅读(350)  评论(0编辑  收藏  举报

导航