Why is this program interrupted?

I wrote a program called Mathtext . This program gives plain text “style” by shifting certain ranges of characters into Unicode ranges, such as “mathematical alphabetic characters,” to get italic text, bold, serifs, etc.

It works like a phased interpreter, like a shell that displays the translated string after entering the string. This means that the files can be cat / piped in to translate the entire file, as well as the fact that you can "exit" the "shell" by pressing the ^ D button, which is detected by pressing the stdin EOF button.

Everything works. However, when I press ^ D and exit, it disappears. I still can not understand what causes this.

Compiling with -g -O0 helps a bit; Now I know that the problem arises from calling strlen in transpose when pressing the ^ D button. However, transposing should never be called during ^ D, since eof is true!

  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 
+4
source share
3 answers

In most cases, using feof() is a mistake - and this program perfectly demonstrates this in this main loop:

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

At the end of the file, fgets() will return NULL , and then the next call to feof() will return true. Thus, the correct approach is to check the return value of your input function - and since you are doing this test anyway, there is no need to call feof() (unless you want to distinguish the file error from the end of the file).

 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(); } 
+3
source

Your program casts NULL, since fgets returns NULL on error or EOF, and you pass it directly for transposition, which naively uses the result.

+3
source

feof cannot predict the future. He does not know that this is the end of the file until you actually press the ^ D key, and by this time your program will return waiting for input to fgets . Reading the file will not result in an error, because all input data is already present at the beginning. Check for NULL in the transpose function.

+1
source

All Articles