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.
Related
This question already has answers here:
printf anomaly after "fork()"
(3 answers)
fork() branches more than expected?
(3 answers)
Closed last year.
I have the following C code:
#include <stdio.h>
#include <unistd.h>
int main()
{
int i, pid = 0;
for (i = 0; i < 3; i++)
{
fork();
pid = getpid();
printf("i=%d pid=%d\n", i, pid);
}
return 1;
}
Which is supposed to create a total of 7 new processes after all the iterations in the loop. Analyzing it you can see that 14 lines should be printed before all the processes finish, and that is exactly what you see when you execute it from the command line.
However, when you redirect the output to another file ./main > output.txt; cat output.txt, you get a completely different situation. In total, 24 lines are always printed and some of them are repeated for the same i and pid values, and the amount of repetition seems consistent. I'm attaching a screenshot for clarification here Execution example. The system that I'm using is Ubuntu 20.04.3 in a VirtualBox VM.
I really don't understand why that is happening, I'm guessing it has something to do with race conditions on the output buffer or some other conflict when multiple processes are writing to the file, but that doesn't explain to me why it doesn't happen on the terminal. Can anybody explain this odd behaviour? Thanks!
When the standard output is a terminal, the stream is typically line buffered. The C standard requires it not be fully buffered, meaning it must be line buffered or unbuffered; C 2018 7.21.3 6 says:
… As initially opened, … the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.
When the program executes printf("i=%d pid=%d\n", i, pid);, the output is immediately sent to the terminal, either because the stream is line buffered and the new-line character causes the output to be sent or because the stream is unbuffered and the output is always sent in each printf. Then, when the program forks, there is no pending output, because it has already been sent to the terminal. Each forked instance of the program prints only its own output.
When the standard output is redirected to a file, the stream is fully buffered. Then, when the program executes printf("i=%d pid=%d\n", i, pid);, the data is held in a buffer inside the program. It is not sent to the terminal immediately. (It will be sent when the buffer is full or when a flush is requested, which occurs automatically at normal program termination.) When the program forks, the buffer is copied along with the rest of the program state. Each forked instance of the program accumulates output in the buffer.
When each forked instance of the program exits, pending data in its buffers are flushed. Thus includes both data added by that particular instance and data that was put into the buffer in parent processes and copied by the fork. Thus multiple copies of data are printed.
To resolve this, execute fflush(stdout); immediately before fork();. This flushes the buffer before forking. Alternately, request that the stream be line-buffered by executing setvbuf(stdout, NULL, _IOLBF, 0); at the start of main.
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.
This question already has answers here:
printf anomaly after "fork()"
(3 answers)
Closed 8 years ago.
I am trying to understand fork(), and so I put together the following example:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void main()
{
if(fork()==0)
{
printf("2");
if(fork()==0)
{
printf("4");
}
else
{
printf("3");
}
}
else
{
printf("1");
}
}
When I was tracing this on paper, I drew the following sketch:
So I believe the output should be 1234. However, when I run this code, the output is 12324. Why is that? Where is my mistake?
Update:
After reading the comments, it was suggested to do any of the following
Add \n to each printf statement
OR: Add fflush(stdout); after each printf statement
OR: Add setbuf(stdout, NULL); <---- this is what I ended-up doing :)
After updating my code, the output was indeed 1234.
printf() output is usually line-buffered. So when you fork(), the new processes gets the copy of the buffer as well. When the process exits, the whole buffer is flushed (or anytime it's flushed in the code or whenever the buffer becomes full). Hence, you see a copy of printf's output one more time.
1) You can flush it after each printf() call by using fflush(stdout);
2) or using \n for example:
printf("2\n");
Another way is to disable the buffering with:
setbuf(stdout, NULL);
Your analysis is almost correct. However, printf does not necessarily write immediately do file descriptor - output is buffered inside the process. The second process does fork after putting 2 in the buffer. Both second and third processes will have it in the buffer and print 2.
If you do printf("2\n") instead new line character will force printf to flush the buffer and you will see only one 2.
This question already has answers here:
Working of fork() in linux gcc [duplicate]
(5 answers)
Closed 8 years ago.
I am using gcc compiler on linux.
When I run this code (Notice"\n" is not present after hello world in printf)
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
printf("Hello world");
fork();
}
I GET THIS OUTPUT: Hello worldHello world
On the other hand
When I run this code (Notice"\n" is present after hello world in printf)
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
printf("Hello world\n");
fork();
}
I GET THIS OUTPUT: Hello world
Can someone describe in detail that, why omitting or leaving "\n" prints "Hello world" twice?
To elaborate on the answer in the linked question and relate it to your question, stdout generally buffers input until it sees a \n, or you explicitly fflush it.
When you have the \n there, you are making it flush before the fork().
Without the \n, it flushes after the fork, so it will exist in both processes.
In the linked question, they talk about fflush(), but \n has the same effect of causing stdout to flush.
You will see only one print with the program below as well:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
printf("Hello world");
fflush(stdout);
fork();
}
Edit: Due to a comment from Dabo, \n will only cause a flush if stdout is in line buffering mode instead of full buffering mode. We can observe in the following program that we still see the string printed twice, even with \n, when full buffering mode is turned on using setvbuf.
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
setvbuf(stdout, NULL,_IOFBF, BUFSIZ);
printf("Hello world\n");
fork();
}
Output:
Hello world
Hello world
Not having the \n means that "hello world" is still in memory - ready to go one its merry way to the terminal.
fork will make a duplicate of this memory - i.e. now you have two processes with the same "hello world" in memory. When the program terminates it will flush this to stdout. I.e. getting it twice.
But if you put the \n in - it gets flush to stdout immediately. Hence this buffer will be empty before the fork is called.
I would say both versions are incorrect. The C runtime will register atexit handlers to flush standard buffers when exit() is called. The proper way to cause your program print only once is to call _exit(0); in child process. This way your child won't call atexit ( which in turn won't flush buffers twice)
if (fork() == 0)
_exit(0);
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Working of fork() in linux gcc
Why does this code print two times?
#include<stdio.h>
main()
{
printf("hello\n");
fork();
}
The above code prints "hello" one time.The code below prints "hello" two times.
#include<stdio.h>
main()
{
printf("hello");
fork();
}
The code above prints "hello" two times.
Please Somebody explain this strange behavior.
It's not guaranteed to behave in this way, but the usual behaviour is: With
printf("hello");
the "hello" is printed to the output buffer, but that buffer is not yet flushed. Then upon the
fork();
the program state is copied to the child process, including the non-empty output buffer. Upon exit, the output buffers of parent and child are both flushed.
With the newline, the output buffer is flushed before the fork().