8
votes

Fread / fTell apparemment brisé sous Windows, fonctionne bien sous Linux

Voici donc le problème, je lis un fichier de niveau pour mon jeu, fonctionne bien sous Linux: xxx pré>

mais sous Windows, je reçois le résultat suivant: p>

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;
}


0 commentaires

3 Réponses :


23
votes

Ouvrez votre fichier en mode binaire: xxx

en mode texte, il se peut que des traductions se produisent pour correspondre au codage dépendant du système d'exploitation de par exemple. ligne se nourrit de la bibliothèque C.


1 commentaires

Euh ..... mon cerveau doit avoir pris de sérieux dommages au cours des derniers jours en raison de la chaleur ... -.- "Cela fonctionne maintenant, merci!



5
votes

ftell et fseek ne fonctionnera que comme décalage d'octet si vous ouvrez le fichier en mode binaire (c.-à-d. "RB" de "r" ). Sinon, vous ne pouvez que fseek sur des choses qui ont déjà été renvoyées par fTell ; Le résultat de fseek ne sera pas un décalage d'octet.

Le mode binaire fait la différence sur Windows dans laquelle le mode texte mappe le retour de chariot de caractères, la séquence d'alimentation de la ligne à un seul caractère de nouvelle ligne. Aucun mappage n'est nécessaire sur Linux.


1 commentaires

Cela a fait l'affaire, même si je trouve toujours un peu étrange que la Fread fait simplement confiance à la valeur de FTELL. Mais une question reste, pourquoi utilise-t-elle le premier octet (C8) dans le fichier sous forme de décalage?



1
votes

Vous ne devez pas utiliser ftell et fseek pour déterminer la taille d'un fichier car il pourrait s'agir de la source de VERFERABILITES:

https://www.securecoding.cert.org/confluence/display/c/fio19-c.+do+not+ UTILISATION + FSEAK% 28% 29 + et + FTELL% 28% 29 + TO + Compute + Taille + de + A + Régulier + Fichier


1 commentaires

Contenu déplacé vers SECURECODING.CERT.ORG/CONFLUENCE/DISPLAY/C/...