简体   繁体   English

fread / ftell显然在Windows下崩溃,在Linux下运行良好

[英]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" ), ftellfseek仅作为字节偏移工作。 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: 您不应该使用ftellfseek来确定文件的大小,因为它可能是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.

相关问题 对solaris和linux下的struct diffrent的恐惧 - fread of a struct diffrent under solaris and linux 网络程序在Linux下工作,在Cygwin下不行 - Network program works in Linux, not under Cygwin mingw 下的 fread() 无法正常工作 - fread() under mingw not working properly Windows下用cygwin编译的C程序可以正常工作,Linux下分割错误。 Cygwin GCC是“坏”的吗? - C program compiled with cygwin in Windows works, segmentation fault under Linux. Is cygwin GCC 'bad'? 这个C程序在Windows中可以正常工作,但在Linux中不能正常工作 - This c program works fine in windows but not working in Linux sed命令在Shell终端下工作正常,但在C代码下的“ system()”调用中失败 - sed command works fine under shell terminal, but fails in 'system()' call under C code 如何在Linux的Windows共享(LINUX)下映射文件? - How to mmap in Linux a file under Windows' share (LINUX)? 我的程序在Windows机器上崩溃,但在Linux上运行正常 - My program crashes on the Windows machine yet it works fine on the Linux 如何在Windows和Linux下链接到OS C库? - How does linking to OS C libraries under Windows and Linux work? 在 Windows 和 Linux 下将 UTF-16 转换为 UTF-8,在 Z0D61F8370CAD1D412F80ZB84D1 - Convert UTF-16 to UTF-8 under Windows and Linux, in C
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM