Question

J'ai écrit un programme appelé Mathtext . Ce programme donne le texte brut « style » en déplaçant certaines plages de caractères Unicode dans les gammes telles que les « symboles mathématiques » pour type lettre produire italique texte brut, gras, serif, etc.

Il fonctionne comme un interprète en ligne par ligne, comme une coquille, sortir la ligne traduite après une ligne est entrée. Cela signifie que les fichiers peuvent être cat / canalisé pour traduire un fichier entier, ainsi que le fait que vous pouvez « sortie » de la « coquille » en appuyant sur ^ D, qui est détecté par stdin frapper EOF.

Tout fonctionne. Cependant, quand je presse ^ D et la sortie, il segfaults. Je ne peux toujours saisir pas tout à fait ce qui est à l'origine de cette.

Compiler avec -g -O0 aide un peu; Je sais maintenant que le problème se pose d'un appel strlen à quand ^ D Transpose est enfoncée. Cependant, la transposition ne devrait jamais être appelé pendant ^ D, comme EOF est vrai!

Program received signal SIGSEGV, Segmentation fault.
__strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:31
31    ../sysdeps/x86_64/multiarch/../strlen.S: No such file or directory.
    in ../sysdeps/x86_64/multiarch/../strlen.S
(gdb) where
#0  __strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:31
#1  0x0000000000400b0e in transpose (s=0x0, capsDelta=120263, smallDelta=120257, numDelta=0) at mathtext.c:58
#2  0x0000000000400e2b in main (argc=2, argv=0x7fffffffe4b8) at mathtext.c:92
Était-ce utile?

La solution

La plupart des utilisations de feof() sont un bug - et ce programme démontre parfaitement dans cette boucle principale:

char temp[1048576];
do {
    if (!strcmp(argv[1], "serifb"))
        transpose(fgets(temp, 1048576, stdin), 119808 - 'A', 119834 - 'a', 120782 - '0');
    else if (!strcmp(argv[1], "serifi"))
        transpose(fgets(temp, 1048576, stdin), 119860 - 'A', 119886 - 'a', 0);
    else if (!strcmp(argv[1], "serifbi"))
        transpose(fgets(temp, 1048576, stdin), 119912 - 'A', 119938 - 'a', 0);
    else if (!strcmp(argv[1], "sans"))
        transpose(fgets(temp, 1048576, stdin), 120224 - 'A', 120250 - 'a', 120802 - '0');
    else if (!strcmp(argv[1], "sansb"))
        transpose(fgets(temp, 1048576, stdin), 120276 - 'A', 120302 - 'a', 120812 - '0');
    else if (!strcmp(argv[1], "sansi"))
        transpose(fgets(temp, 1048576, stdin), 120328 - 'A', 120354 - 'a', 0);
    else if (!strcmp(argv[1], "sansbi"))
        transpose(fgets(temp, 1048576, stdin), 120380 - 'A', 120406 - 'a', 0);
    else if (!strcmp(argv[1], "mono"))
        transpose(fgets(temp, 1048576, stdin), 120432 - 'A', 120458 - 'a', 120822 - '0');
    else if (!strcmp(argv[1], "fullwidth"))
        transposeBlock(fgets(temp, 1048576, stdin), '!', '~', 65281 - '!');
    else return help();
} while(!feof(stdin));

À la fin de fichier, fgets() retournera NULL, puis la prochaine invocation de feof() retourne vrai. Donc, la bonne approche est de tester la valeur de retour de votre fonction d'entrée - et puisque vous faites ce test de toute façon, il n'y a pas besoin d'appeler feof() (sauf si vous voulez distinguer une erreur de fichier de fin de fichier)

char temp[1048576];
while (fgets(temp, sizeof temp, stdin) != NULL) {
    if (!strcmp(argv[1], "serifb"))
        transpose(temp, 119808 - 'A', 119834 - 'a', 120782 - '0');
    else if (!strcmp(argv[1], "serifi"))
        transpose(temp, 119860 - 'A', 119886 - 'a', 0);
    else if (!strcmp(argv[1], "serifbi"))
        transpose(temp, 119912 - 'A', 119938 - 'a', 0);
    else if (!strcmp(argv[1], "sans"))
        transpose(temp, 120224 - 'A', 120250 - 'a', 120802 - '0');
    else if (!strcmp(argv[1], "sansb"))
        transpose(temp, 120276 - 'A', 120302 - 'a', 120812 - '0');
    else if (!strcmp(argv[1], "sansi"))
        transpose(temp, 120328 - 'A', 120354 - 'a', 0);
    else if (!strcmp(argv[1], "sansbi"))
        transpose(temp, 120380 - 'A', 120406 - 'a', 0);
    else if (!strcmp(argv[1], "mono"))
        transpose(temp, 120432 - 'A', 120458 - 'a', 120822 - '0');
    else if (!strcmp(argv[1], "fullwidth"))
        transposeBlock(temp, '!', '~', 65281 - '!');
    else return help();
}

Autres conseils

Votre programme est déréférencement NULL, NULL car fgets retourne en cas d'erreur ou EOF, et vous passez directement à ce transposent qui utilise le résultat naïvement.

feof ne peut pas prédire l'avenir. Il ne sait pas que c'est la fin du fichier jusqu'à ce que vous appuyez sur la touche ^ effectivement D, date à laquelle votre programme est de retour en attente d'entrée dans fgets. La lecture d'un fichier ne produirait pas l'erreur, car toutes les entrées est déjà présent au début. Vérifiez la valeur NULL dans votre fonction Transpose.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top