-1

I build a small program that simply copy the text from an input.txt file to an output.txt file. It works with no apparent problem with the command:

./myCopier.txt < rand.txt > randout.txt

on a GCC89 compiler, used for didactic purposes.

#include<stdio.h>

int main(void){
        int c;

        while ((c = getchar()) != EOF)
                putchar(c);

        /*The text in printf() does not appear anywhere*/

        printf("My theories and toughts!\n");
}

Later, I add printf() in order to print my thoughts about how the program worked. It compiles without errors or warnings even with restrictive parameters (-Wall), but this text does not appear in any place. By any place, I mean both output.txt and the standard output.

I am thinking that:

  1. The command ./myCopier.exe alone clearly create an endless loop. Without text input there is no EOL character, hence the print() command is never reached.
  2. So, why when the input is provided, the printf() command has no apparent effect? I'd expect the text from printf()to appear on the standard output, just when the loop closes and output.txt is created. Why does it not occur?
  3. My theory is that ./myCopier.txt < rand.txt > randout.txt does not allow it. For some reason, it makes the program only transfer the input to the output, "ignoring" everything does not come from the input. Am I correct? If so, why?

If you are interested in the problem with deeper detail, here is the assembly code:

http://text-share.com/view/79f31f38

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Worice
  • 3,847
  • 3
  • 28
  • 49
  • Could you show what assembly is generated by your compiler? – Siguza Jul 06 '17 at 11:09
  • 1
    Also if memory serves me right, the permission to omit an explicit `return` statement in `main()` was introduced in C99, which would mean that by the C89 standard your program invokes undefined behaviour. – Siguza Jul 06 '17 at 11:12
  • I think there's some misunderstanding somewhere, that what you think is happening is not, in fact, happening. The third point would require something to be magic, to do that comparison. Perhaps you added the `printf()`, but failed to re-compile afterwards and continued to run the old binary? – unwind Jul 06 '17 at 11:14
  • @unwind I agree. Unfortunately, I checked several times, getting the same result. – Worice Jul 06 '17 at 11:17
  • @Siguza do you mean that a return statement cannot be omitted? In my case, it can be omitted in similar cases. Just to be sure, I added it, with no effect. – Worice Jul 06 '17 at 11:22
  • Cannot reproduce. What compiler are you using? – Serge Ballesta Jul 06 '17 at 11:23
  • @Worice Can you delete your binary first, to absolutely rule out using an old version of your code? What does happen when you start it without io-redirection in a terminal window and press CTRL+Z (EOF on Windows) or CTRL+D (on unix)? I assumed you use windows because of the .exe-suffix, but it seems you work with linux? – Ctx Jul 06 '17 at 11:25
  • @SergeBallesta I am using a gcc89 compiler on Lubuntu guest virtual machine. – Worice Jul 06 '17 at 11:25
  • I think you are running a old version of the program. You should control twice your PATH, the executable you actually run and its date. – Serge Ballesta Jul 06 '17 at 11:28
  • @Ctx without io-redirection the program works without run-time error. It does not produce any output because. I suppose, the `while` loop cycles endlessy, not allowing the program to execute the `printf` instruction. – Worice Jul 06 '17 at 11:29
  • 2
    @Worice As I said, you can signal EOF from stdin by pressing CTRL+D on unix or CTRL+Z on windows terminating your loop – Ctx Jul 06 '17 at 11:30
  • @Ctx it correctly exits the loops and prints the phrase when the program is launched without I/O redicrection. – Worice Jul 06 '17 at 11:34
  • 2
    @Worice Then for some reason the output buffer isn't flushed... Does an `fflush(stdout);` after the `printf()` make it work with io-redirection? – Ctx Jul 06 '17 at 11:36
  • @Ctx it worked! I had not idea of such an option, I will have to further investigate about it. – Worice Jul 06 '17 at 11:38
  • 1
    @Worice It's still strange, the output buffer should be flushed implicitly on exit! How exactly do you compile and link your binary? – Ctx Jul 06 '17 at 11:39
  • gcc myProgram.c -o myProgram.x -Wall – Worice Jul 06 '17 at 11:43
  • What is a "GCC89 compiler"? Use a more recent version! – too honest for this site Jul 06 '17 at 11:51
  • 1
    Throw out whatever old junk you are compiling with and get a standard compliant version of GCC. You should be able to compile as `gcc -std=c11 -pedantic-errors -Wall -Wextra`. There aren't any reasons to compile your code as GNU C/gnu90 unless you have very special requirements. – Lundin Jul 06 '17 at 12:23
  • Thank you @Lundin for your suggestion. Unfortunately, for a while I will have to work with the '89 version. I hope i will change soon. – Worice Jul 06 '17 at 12:59

1 Answers1

3

Omitting the return statement in main() causes undefined behavior in C89/C90.

Normally, returning from main() forces the output buffer to be flushed. If you omit the return statement, anything can happen.

  • Try to add return 0 at the end of main() as was required in C90. GCC in c90/gnu90 mode will warn you otherwise: "control reaches end of non-void function".
  • Try to add fflush(stdout);.
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Sounds good, but [OP claimed in comments](https://stackoverflow.com/questions/44947173/hidden-printable-text#comment76869929_44947173) to have added the `return` statement without success. Possible that OP was mistaken, forgot to compile with changes, etc.... – ad absurdum Jul 06 '17 at 12:27
  • @DavidBowling If there is an explicit return statement, the program is required to flush the buffers and thereby print the text to stdout by then (if not before). If it doesn't, the compiler is non-conforming. – Lundin Jul 06 '17 at 12:29
  • Agree, and that was my first thought too. Just pointing out OP's comment. – ad absurdum Jul 06 '17 at 12:31
  • In the C standard Theory abstracting from the implementation @Lundin is right. But in the real world gcc exit code on W & L flushes the buffers anyway. Bare metal implementations mostly do not (at least those I use). So those theoretical pointless discussions, do not help in the real world at all. – 0___________ Jul 06 '17 at 12:43
  • @PeterJ It is not theory. The C standard says that calling return from main() is the same thing as calling the exit() function. Which in turn says that upon exit() all buffers must be flushed. If there is no return, then you can't expect the buffers to be flushed, simple as that. – Lundin Jul 06 '17 at 12:47
  • Thank you for your explanation. The issue drove me to to fields that still go beyond my present skills. For now :) In any case, now I have a better grasp on several things that were bothering me. – Worice Jul 06 '17 at 13:11