1

MinGW m'a foutu en pétard ><

Je fais du C et je parse un fichier texte.
Je détermine la taille d'un fichier avec un classique
        fseek(src, 0, SEEK_END);
        buffer_size = ftell(src) + 1; // +1: terminal 0. ftell returns -1 if it failed
Ok
Ensuite je crée le buffer, je mets son dernier octet à 0, et je fais un fread pour lire le fichier. Ok.
Puis je m'étonne d'avoir du garbage à la fin du buffer. Edition du fichier à l'éditeur hexa, tout est ok. C'est un bête fichier texte créé avec Notepad... Donc les fins de lignes sont des CR/LF
Puis j'ai compris... MinGW transpose tout seul les CR/LF en LF. Donc mon buffer est trop grand. Donc il y a du garbage à la fin. Tout ça parce que MinGW se permet de faire des conversions dans mon dos.
Vu que je peux pas déboguer sous Windows, je retour sous Linux. Et là, ça marchait au poil, avec le même fichier. Et ça merdait sous Windows.
Purée, 1h30 perdue à réfléchir à cette mayrde vtffvtffvtffvtffvtffvtffvtff

2

C'est pas MinGW, c'est dans la spéc du C. Perso j'ouvre toujours les fichiers texte en mode binaire, et je fais mes propres fonctions de parsing, pour avoir un truc qui marche pareil quelle que soit la plateforme.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

3

Encore mieux ! Si encore ça avait été dans une page de man, j'aurais trouvé, vu que j'ai tendance à toujours lire et relire la doc des fonctions standard pour ne pas rater le petit corner case qui casse tout...
Et comme la spéc du C ne traine pas sur ma table de chevet, ben je l'ai eu dans l'OS.

Pardon quand même à MinGW, j'ai cru que cette conversion était faite pour des questions de compatibilité d'EOL.

Ceci dit :
-> ça marchait bien sous Linux, pourquoi ?? Les hasards d'un '\0' qui trainait au bon endroit dans le buffer alloué ?
-> le 'b' de fopen n'a pas l'air standardisé (cf la page qui dit qu'il est totalement ignoré), donc remplacer un truc pas standard/portable par un autre, très peu pour moi

4

Par ce que en mode texte la libc traite le retour à la ligne standard de l’environnement, à savoir : "\n" pour les Unix-like(dont Linux et Mac OS X), "\r" sous les anciens Mac OS et "\r\n" sous Windows.
La doc que tu lis doit être une doc spécifique UNIX.
avatar

5

Donc je ne comprends pas : pourquoi MinGW transforme \r\n en \n, alors que je suis sous Windows ?

6

Le K&R dit ceci :
Certains systèmes font la distinction entre les fichiers en mode texte ou binaire ; pour ces derniers, il faut rajouter un "b" à la fin de la chaîne de caractères de mode.
Donc c'est valide d'ignorer "b" si les fichiers sont toujours ouverts en mode binaire (c'est le cas de Linux), mais c'est bien un paramètre standard et valide.
Folco (./5) :
Donc je ne comprends pas : pourquoi MinGW transforme \r\n en \n, alors que je suis sous Windows ?
Parce que \n représente la fin de ligne en C. Si MinGW (et les autres implémentations) ne faisaient pas ça, les programmes C ne pourraient pas gérer correctement les fichiers textes natifs sous Windows.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

7

Donc je me prends la tête pour rien à gérer \r\n en C après un fopen/fread/fgets ?
        eol = strchr(parser, '\n');
        if (eol != NULL) {
            *eol = '\0';
            char* one_before_eol = eol - 1;
            if ((one_before_eol >= buffer) && (*one_before_eol == '\r')) {
                *one_before_eol = '\0'; // It was CRLF
            }
        
Et donc j'en déduis qu'il est plus avantageux d'ouvrir les fichiers en mode texte et non binaire, et de ne gérer que des fins de lignes unix, non ? La libc locale devrait faire le boulot de traduction ?

Dernière question, j'imagine que quand je fais un fprintf(dest, "\n");, MinGW va écrire \r\n ? (ok, je peux aller vérifier ^^)
edit -> la réponse est oui, merci https://hexed.it/?hl=fr happy

8

C'est aussi dépendant des paramètres de la compilation de MinGW.

Mais sinon oui, ouvrir un fichier en binaire ("rb") t'offres plus de garanti de retrouver tes petits.

9

Je propose pourtant le contraire :
Folco (./7) :
Et donc j'en déduis qu'il est plus avantageux d'ouvrir les fichiers en mode texte et non binaire, et de ne gérer que des fins de lignes unix, non ? La libc locale devrait faire le boulot de traduction ?
Qu'est-ce qui cloche là-dedans ?

10

Si tu veux traiter du texte en utilisant la norme de retour a la ligne préférée pour ton OS et ton compilateur, le mode texte est en effet fait pour ça.
Le mode binaire comme son nom l'indique permet d'avoir un résultat binaire garanti qui ne prend pas en compte les considérations de texte. Ça te permet d'être certain du résultat binaire de ton fichier quel que soit l'OS.
avatar

11

Ah ok, ce mode binaire est donc là pour éviter toute conversion intempestive de la part de l'OS, il est donc à utiliser quand on veut spécifiquement lire un fichier binaire. Parfait merci. smile

12

Le mode texte permet en outre de streamer ligne à ligne.

Ce que le mode binaire ne permet pas.

13

En effet. Merci à tous pour vos bons conseils et références K&Riques happy

14

L'agence tous K&Risques ?

15

Exactement, merci de préciser, même si je pense que tout le monde avait compris.

16

Zero: non c'est un choix de MinGW, comme il est du demi UNIX/POSIX, il utilise les fin de lignes POSIX/UNIX

J'ai pas mémoire que la norme C force les fin de lignes, en tout cas les compilateurs ne sont pas chiant avec ca.

Par contre oui c'est sur utiliser fpos/ftell pour un fichier ouvert en mode texte c'est voué a l'échec, tu potentiellement avoir le nombre de caractères mais pas bien plus, la taille en octet risque en effet de ne pas être correcte.

il faut mieux utiliser fstat pour avoir la taille de manière fiable:

http://linux.die.net/man/2/fstat

Sinon certains OS ne font pas la distinction entre binaire et texte, Windows le fait, Unix/linux non. L'ouverture avec le mode text ne diot vraiment etre fait que pour les fichiers texte ou tu n'aura aucun caracteres non affichable.

Et il vaux mieux toujours signaler t/b suivant le type de fichier qu'on ouvre et meme si on utilise que UNIX/Linux, au moins ca donne une info claire, et si qq'un veux porter sous windows ca auras moins de chance de foirer.
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

17

Ok, merci pour le lien et les conseils chinois

18

Godzil (./16) :
Zero: non c'est un choix de MinGW, comme il est du demi UNIX/POSIX, il utilise les fin de lignes POSIX/UNIX
J'ai pas mémoire que la norme C force les fin de lignes, en tout cas les compilateurs ne sont pas chiant avec ca.
Le type de fin de ligne utilisé par la libc pour les fichiers en mode texte est celui du système natif. Plus précisément, le K&R spécifie :
La bibliothèque peut gérer des flots en mode texte ou des flots binaires, bien que sur certains systèmes, notamment UNIX, ces flots soient identiques. Un flot en mode texte est une suite de lignes ; chaque ligne est constituée de caractères (éventuellement aucun) et se termine par '\n'. Un environnement particulier peut avoir besoin de convertir le flot de texte en une autre représentation, ou vice-versa (par exemple, remplacer les '\n' par des séquences « retour chariot, avance de ligne »).
Donc sous Windows, ce sera CR+LF, même avec MinGW, vu qu'au final les exécutables compilés tournent sous Windows. Si MinGW avait utilisé le standard Unix, ça aurait empêché la compatiblité entre les softs natifs Windows et ceux compilés avec MinGW.

Sous Linux il n'y a pas de conversion, donc pas de différence entre le mode texte et le mode binaire, tout simplement parce que le C a été conçu sous Unix, donc ils ont utilisé la même convention pour le langage que pour le système.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

19

Quand tu parles de K&R tu parle de quelle edition?

Je serait curieux de ce que dit les version C99++
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

20

Celle que j'ai citée (version papier) est la 2ème édition, de 1989.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

21

Ok, alors vaux mieux l'appeler ANSI ^^ (K&R fait habituellement référence à la premiere edition de 197x)
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

22

Pas faux ^^
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

23

Ah, un grand classique l'ouverture de fichier texte en C grin

Dans le même genre, j'ai récemment renoué avec dos2unix à cause de cygwin et des erreurs qu'il fait en exécutant des scripts shell enregistrés à la Windows, que du bonheur.
avatar
Que cache le pays des Dieux ? - Forum Ghibli - Forum Littéraire

La fin d'un monde souillé est venue. L'oiseau blanc plane dans le ciel annonçant le début d'une longue ère de purification. Détachons-nous à jamais de notre vie dans ce monde de souffrance. Ô toi l'oiseau blanc, l'être vêtu de bleu, guide nous vers ce monde de pureté. - Sutra originel dork.

24

Petit 'truc' pour savoir si un fichier ou un dossier existe, sans avoir à l'ouvrir :

#include <io.h> // _taccess

if(0 == _taccess(file_or_dir, 0))

25

Hummmmmm une fonction "lib c" qui commence par _, ça commence mal, c'est souvent du Microsoft only, et résultat, c'est dunmicrosoft only.

stat / lstat / fstat fait ca très bien et au moins fait partit de la Libc posix standard
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

26

Au passage, utiliser fstat() pour obtenir la taille d'un fichier qu'on va lire n'est pas une bonne idée : y'a une race condition potentielle, la taille du fichier peut changer entre l'appel à fstat() et l'ouverture du fichier (même si c'est un cas rare).
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

27

Fstat non parce que c'est sur une file descriptor. stat oui par contre.

Enfin ceci dit ca peux aussi arrivee avec d'autre moyens avec le fichier ouvert, suivant l'OS ouvrir un fichier ne va pas le bloquer pour les autres apps et donc certaines peuvent le modifier, et sois tu n'auras pas la dernière version soit pire tu as le risque de l'écraser.
Et si l'OS est mal foutut, on peux meme imaginer que ce que tu lit peux changer
avatar
Proud to be CAKE©®™


GCC4TI importe qui a problème en Autriche, pour l'UE plus et une encore de correspours nucléaire, ce n'est pas ytre d'instérier. L'état très même contraire, toujours reconstruire un pouvoir une choyer d'aucrée de compris le plus mite de genre, ce n'est pas moins)
Stalin est l'élection de la langie.

28

Ah oui tu as raison, j'avais mal lu smile
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo