Why output is different between to shell and to a file - c

Consider the following program.
main() {
printf("hello\n");
if(fork()==0)
printf("world\n");
exit(0);
}
Compiling this program using ./a.out gives the following Output:
hello
world
compiling this program using ./a.out > output gives the output in the file called 'output' and appears to be like this:
hello
hello
world
Why is this so?

Because when you output to shell stdout is usually line buffered, while when you write to a file, it's usually full buffered.
After fork(), the child process will inherit the buffer, when you output to shell, the buffer is empty because of the new line \n, but when you output to a file, the buffer still contains the content, and will be in both the parent and child's output buffer, that's why hello is seen twice.
You can try it like this:
int main() {
printf("hello"); //Notice here without "\n"
if(fork()==0)
printf("world\n");
exit(0);
}
You will likely see hello twice when output to shell as well.

This answer after Yu Hao 's answer . He already explain a lot .
main() {
printf("hello\n");
fflush(stdout);//flush the buffer
if(fork()==0)
printf("world\n");
exit(0);
}
Then you can get the right output.

Related

A question about the "watch" command in Linux with the "fork()" system call [duplicate]

This question already has answers here:
printf anomaly after "fork()"
(3 answers)
Closed 25 days ago.
This post was edited and submitted for review 24 days ago.
I have a C programme like this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf("hello world (pid:%d)\n", (int)getpid());
int rc = fork();
if (rc < 0)
{ // fork failed; exit
fprintf(stderr, "fork failed\n");
exit(1);
}
else if (rc == 0)
{ // child (new process)
printf("hello, I am child (pid:%d)\n", (int)getpid());
}
else
{ // parent goes down this path (main)
printf("hello, I am parent of %d (pid:%d)\n",
rc, (int)getpid());
}
return 0;
}
After finishing the gcc compilation, I got the "a.out" executable file. And I got the correct programme output in the Linux shell.
hello world (pid:1056088)
hello, I am parent of 1056089 (pid:1056088)
hello, I am child (pid:1056089)
But if I use the watch command to execute it, I got the output like this:
hello world (pid:1056155)
hello, I am parent of 1056156 (pid:1056155)
hello world (pid:1056155)
hello, I am child (pid:1056156)
I don't know why if I use the watch command, there would be an extra line in the output.
I have tried to delete the line "printf("hello world (pid:%d)\n", (int)getpid());", there would be no difference between the outputs. And if I add the "fflush(stdout);" line under it, it also has no difference between the outputs.
Now I know that "stdout" is line buffered. But I wonder why the "watch" commmand has the diffwerent output with the "./a.out" format. Is this a bug, or a feature?
I would be appreciate if anybody can explain it to me.
When printing to a pipe, standard output is buffered. When you fork, the whole program is copied to the fork, including the contents of the buffer.
If you print more than just one line, you can see that only the final part of it gets copied and printed twice, e.g.
for (int i = 1; i < 64000; ++i) printf("%d\n", i);
On my machine, everyting up to 63970 gets printed once, the rest is printed twice:
a.out | grep 6397[01]
63970
63971
63971
See also Why does printf not flush after the call unless a newline is in the format string?

Unexpected output on a fork call in C [duplicate]

This question already has answers here:
Why is main called twice?
(3 answers)
Closed 1 year ago.
I encountered this in my school work and it didn't produce what I thought it should:
int main() {
printf("c");
fork();
printf("d");
}
I know there are several things that aren't good about this code (i.e. no parameters in main, no variable for the return value from fork, no return statement at the end, etc.), but this is how it was presented and it's not relevant to my question anyway.
This code produces the output:
cdcd
It was my understanding that when fork is called, both parent and child would resume/begin on the line after the fork call. Based on that, I would have expected the output to be:
cdd
Assuming, of course, that the fork call is successful. Can anyone explain to me why that "c" is printed a second time even though it's on the line before the fork call?
Thanks!
M_MN
You forked your program before flushing stdout (i.e.: data was still in the output buffer). Just call fflush(stdout) to fix it:
❯ cat test.c
#include <stdio.h>
#include <unistd.h>
int main() {
printf("c");
fflush(stdout);
fork();
printf("d");
}
[22:14:01]~/devel
❯ clang test.c -o test
[22:14:07]~/devel
❯ ./test
cdd[22:14:09]~/devel
The reason you're seeing c twice is that the fork() duplicates the unprinted buffered output. You could flush the output stream before the fork():
fflush(stdout);
Or you could set stdout to be unbuffered, but you should do this first, before calling printf() the first time:
setvbuf(stdout, NULL, _IONBF, 0);
Here's what I'm guessing is happening. printf writes to the stream stdout. Since you didn't flush stdout after printing "c" nor did that string end in a new line, the character sat there in a user-space buffer. When you called fork, the child process got a copy of the parent's virtual address space including the buffered text. When both programs exited, their buffers were flushed and so "c" showed up twice.
Try adding fflush(stdout); just prior to the call to fork.

What Race Causes the Output to Look Different?

I was given this question on a midterm last year.
Consider the following program.
#include <stdio.h>
#include <unistd.h>
int main (void) {
int pid = getpid ();
printf ("hello world (pid:%d)\n", pid);
int rc = fork();
if (rc < 0) {
fprintf (stderr, "fork failed\n");
retrun 1;
}
pid = getpid();
if (rc == 0) {
printf ("hello, I am child (pid:%d)\n", pid);
} else {
printf("hello, I am parent of %d (pid:%d)\n", rc, pid);
}
return 0;
}
And consider the following behavior that I got when I compiled and ran this program:
$ gcc -02 -Wall question.c
$ ./a.out # First program run
hello world (pid:20600)
hello, I am parent of 20601 (pid:20600)
hello, I am child (pid:20601)
$ ./a.out | cat # Second program run
hello world (pid:20605)
hello, I am parent of 20607 (pid:20605)
hello world (pid:20605)
hello, I am child (pid:20607)
a) What race could cause the output to look substantially different from either the first or the second run, and what would this output look like?
b) Explain each different in the outputs of the two program runs.
For part (a) I argued that there is a race between the child process and the parent process, and that the child can print before the parent, but apparently that was wrong. Is there any other race that would cause the output to be different? And why is my answer wrong?
For part (b) I am shaky on multiple things. First is that I see the PIDs are different in both runs, but I don't have a good explanation for that. Second that extra hello world in the second run is because of the way the program is being run with a pipe and the cat command?
The problem is that you pipe the output to cat.
By default, when stdout is connected to a terminal or console, then stdout is line buffered which means that the internal buffers are flushed at newline (or when the buffer is full, or when fflush is called).
But when stdout is not connected to a terminal or console, like when it is connected to a pipe, it becomes fully buffered. This means it will only be flushed if the buffer becomes full or fflush is called. Printing newlines doesn't do anything special, the newline is just added to the buffer.
Now because stdout is fully buffered the buffer with the contents of the first printf call will be copied to the child process as part of the fork call, and will be flushed when the child process exits.

Unexpected behaviour of fork()

I m doing some C program using fork()
But I'm getting unexpected output.
#include <stdio.h>
main(){
printf("\nStart of Program");
fork();
printf("\nEnd of Program");
}
Output:
Start of Program
End of ProgramStart of Program
End of Program
Why do I get this output ?
Output should be this:
Start of Program
End of Program
End of Program
This issue is happening because of buffering.
Quoting this post.
When the output of your program is going to a terminal (screen), it is line buffered. When the output of your program goes to a pipe, it is fully buffered.
The posts also contains line by line explanation.
This is because of printf(), printf is buffering the output and only print when he reaches a '\n', so when reaching printf("\nEnd of Program"); printf() prints the content of the buffer which is "Start of Program".
Because fork() duplicates your stack, printf() buffer is duplicated too.
Try:
#include<stdio.h>
main(){
printf("Start of Program\n");
fork();
printf("End of Program\n");
}
Few things here need to check.
From where it is printing "student". I do not see any where you are printing student in your code.
The ideal output is
Start of Program
End of Program
End of Program
If you are not getting above output I will suspect, when fork executed and child got created probably your standard output print was not complete. Flush or \n as last char in print is a must to complete the print job,
To verify this what you can do is, before fork just use fflush.
Also in printf use \n as last char.
#include<stdio.h>
main()
{
printf("Start of Program\n");
fflush(NULL);
fork();
printf("End of Program\n");
}
Try this and let us know.
when fork is come then new process is created.
so end of program before fork call process and after fork call is printed. so that's logic.
I compiled that code myself, and I get following output:
Start of Program
End of Program
Start of Program
End of Program
Which is correct since fork() spawns exactly the same child process its forked from.
Edit: Thanks to the comments, I found out whats really going on. Fork behaves as expected, but the input buffer is not getting flushed before the child process is executed. I've modified the original code to this:
#include <stdio.h>
main(){
printf("\nStart of Program\n");
fflush(stdout);
fork();
printf("\nEnd of Program\n");
}
And the output now reads:
Start of Program
End of Program
End of Program
Which indicates that indeed, fork() only spawns the child process executing downwards from after the fork() call.

Understanding why fork gives different result in C

Although there are some similar questions like this and this
I still cannot understand why fork gives different output with the following two codes
#include<stdio.h>
void main()
{
printf("Hello World\n");
fork();
}
Gives output
Hello World
Where as this code
#include<stdio.h>
void main()
{
printf("Hello World");
fork();
}
Gives output
Hello WorldHello World
The second case is clear to me from the other questions, that both processes get a copy of the same buffer. So, after the fork, both processes eventually flush the buffer and print the contents to screen separately.
But I am not clear why the first case is so.
Let me explain it in simple words:
Consider,these two statements:
printf("Hello World")
and
printf("Hello World\n")
The STDOUT is line buffered that is printf will be executed only when the buffer is full or when it is terminated by a new line character
printf("Hello World") will not be guaranteed to display the output unless the
Buffer is full or terminated by new line character..Thus when a fork() is called,
Fork will create a copy of a process,this means that after fork, there are two identical processes,
each having a copy of the FILE* STDOUT Therefore, each process will have the same buffer contents of STDOUT
Since in your second program there is no newline character,
each process has the string in its buffer.
Then each process prints another string, and all of the contents are printed since it is terminated by a new line character. This is why you see two identical outputs.
But
In your first program,there is a new line character and it displays output
immediately after the statement is executed and hence it flushes the contents of buffer..thus when a fork() is called
The process tries to access the buffer but since the buffer is empty,it does not print anything
Thus,the different response is due to Buffering behavior of stdout
Hope it helps!!
It's due to the buffering behavior.
#include<stdio.h>
void main()
{
printf("Hello World\n");
fork();
}
flushes the output before you call fork, so the printing is already finished when it was still only a single process.
As to why printf("Hello World\n"); gets flushed immediately and printf("Hello World"); doesn't isn't that easy. It depends on the situation. In your case you probably ran it in the commandline where line buffering is common, line buffering means that it will be flushed once you got a newline. If you write to files it might buffer more before you get any output and you might see 2 outputs in the first case too.
If you want consistent behavior with flushing you might want to do it yourself.

Resources