[英]fread/ftell apparently broken under Windows, works fine under Linux
So here's the problem, I'm reading a level file for my game, works fine under linux: 所以这就是问题,我正在为我的游戏阅读一个关卡文件,在linux下工作正常:
@0
@12
200x200 version 3
@16
973 blocks
@989
@993
18 zones
But under windows I get the following result: 但在Windows下我得到以下结果:
@0
@212
200x200 version 3
@216
973 blocks
@1200
@1204
18 zones
Uh? 呃? The windows ftell stats with an offset of 200?
窗口的ftell统计数据偏移量为200? Reading the file apparently yields the same data, but fread uses(?) the value of ftell to determine the how many bytes are left in the file that can be read.
读取文件显然会产生相同的数据,但是fread使用(?)ftell的值来确定文件中可以读取的字节数。 So of course I'm running into problems when reading at the end of the file:
所以当我在文件末尾阅读时遇到问题:
@1425
zone#9 2x3 @ 66/9
@1425
zone#10 2x3 @ 66/9
@1425
zone#11 2x3 @ 66/9
@1425
zone#12 2x3 @ 66/9
@1425
zone#13 2x3 @ 66/9
@1425
zone#14 2x3 @ 66/9
etc.
This is the corresponding code(currently a bit ugly due to all the debug prints..): 这是相应的代码(由于所有调试打印,目前有点丑陋..):
void fread_all(void *ptr, size_t size, size_t count, FILE *stream) {
fread(ptr, size, count, stream);
printf("@%ld\n", ftell(stream));
}
bool map_load(struct Map *map, const char *file_name) {
FILE *fp = fopen(file_name, "r");
if (fp != NULL) {
fseek(fp, 0, SEEK_SET);
printf("@%ld\n", ftell(fp));
// Header
int *header = (int*)calloc(sizeof(int), 3);
fread_all(header, sizeof(int), 3, fp);
printf("%dx%d version %d\n", header[0], header[1], header[2]);
map->pos_x = 0;
map->pos_y = 0;
map->map_x = 0;
map->map_y = 0;
map->size_x = header[0];
map->size_y = header[1];
map_zones_remove(map);
free(header);
// Blocks
unsigned int *block_size = (unsigned int*)malloc(sizeof(unsigned int));
fread_all(block_size, sizeof(int), 1, fp);
printf("%d blocks\n", *block_size);
unsigned char *block_data = (unsigned char*)calloc(sizeof(unsigned char), *block_size);
fread_all(block_data, sizeof(unsigned char), *block_size, fp);
unsigned char *tmp = map->blocks;
map->blocks = rle_decode(block_data, *block_size);
free(tmp);
free(block_size);
free(block_data);
// Zones
int *zone_count = (int*)malloc(sizeof(int));
fread_all(zone_count, sizeof(int), 1, fp);
printf("%d zones\n", *zone_count);
int *d = (int*)calloc(sizeof(int), 6);
for(int i = 0, l = *zone_count; i < l; i++) {
fread_all(d, sizeof(int), 6, fp);
map_zone_create(map, d[0], d[1], d[2], d[3], d[4], d[5]);
printf("zone#%d %dx%d @ %d/%d\n", i, d[2], d[3], d[0], d[1]);
}
map_platforms_create(map);
free(zone_count);
free(d);
fclose(fp);
return true;
}
return false;
}
I really have no clue what's going on here. 我真的不知道这里发生了什么。 Compilers are the Visual Studio 10 one and GCC 4.4 under Linux.
编译器是Visual Studio 10和Linux下的GCC 4.4。
Open your file in binary mode: 以二进制模式打开文件:
FILE *fp = fopen(file_name, "rb");
In text mode, there might be translations going on to match the operating system-dependent encoding of eg line feeds to the C library's. 在文本模式中,可能存在翻译以匹配例如换行到C库的操作系统相关编码。
ftell
and fseek
are only going to work as byte offsets if you open the file in binary mode, (ie "rb"
instead of "r"
). 如果以二进制模式打开文件(即
"rb"
而不是"r"
), ftell
和fseek
仅作为字节偏移工作。 Otherwise you can only fseek
to things that have previously be returned by ftell
; 否则,你只能
fseek
到之前已经通过被退回的事情ftell
; the result of fseek
isn't going to be a byte offset. fseek
的结果不会是字节偏移量。
Binary mode makes a difference on windows where text mode maps the two character carriage return, line feed sequence to a single new-line character. 二进制模式在窗口上有所不同,其中文本模式将两个字符回车符,换行序列映射到单个换行符。 No mapping is needed on linux.
Linux上不需要映射。
You should not be using ftell
and fseek
to determine the size of a file since it might be the source of vurnerabilities: 您不应该使用
ftell
和fseek
来确定文件的大小,因为它可能是vurnerabilities的来源:
https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+regular+file https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size + A +常规+文件+
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.