+ 17

Position of output of system() in C/C++

While fiddling around with with sololearn's command processor via the system() function in c/c++, I observed the following things : - output from system function is positioned either at the very top or at very bottom of the output file, and doesn't depend on the the output from the program ( via std::cout or printf() ). - this behaviour is command depended and not depend on where/when the function is called. - it is not a sololearn specific behaviour, same happens with a lot of other online server based IDE's also (like one of codechef). can someone enlighten me about what is going on here ? Here is the code 👇 https://code.sololearn.com/ce2E6cP9P741/?ref=app

4th Feb 2021, 11:34 AM
Arsenic
Arsenic - avatar
16 Antworten
+ 13
Can it be that gcc --version outputs to stderr and gcc --v to stdout, and then sololearn just concatenates stderr and stdout? This test seems to support it: https://code.sololearn.com/cpx12ojjY6hj/?ref=app Edit: like Arsenic noticed it is the other way round: "gcc -v" writes to stderr, and "gcc --version" to stdout
4th Feb 2021, 11:50 PM
Volodymyr Chelnokov
Volodymyr Chelnokov - avatar
+ 7
In the last case the output of the program is piped through a second process, an instance of `more`. The `system` call also creates a process. Apparently (but it's just a hypothesis) `more` buffers the input it receives instead of presenting each line right away.
5th Feb 2021, 2:22 PM
A S Raghuvanshi
A S Raghuvanshi - avatar
+ 6
we know that std cout is ostream object..using just << doesnt mean it will output it to screen..it just stores in buffer..then you have to flush it explicitly using std::flush, or just use std::endl (implicitly flushed). idk about the system function though.
4th Feb 2021, 12:14 PM
durian
durian - avatar
+ 6
Volodymyr Chelnokov I think you mean "gcc --version" to stdout and "gcc -v" to stderr. If so, then that makes a whole lot of sense , as it is a fact that sololearn's code playground and other online IDEs that I used, merges stdout and stderr at the end (you can look at the attached code to have a look at bashfile which soloearn uses to run the code as a proof) And from your code , I am pretty convinced that "gcc -v" outputs in stderr stream. ( Why it is doing so is still a mystery ) https://code.sololearn.com/cQM7WC5FCfbA/?ref=app
5th Feb 2021, 12:36 AM
Arsenic
Arsenic - avatar
+ 6
/*Using fedora here, and the code you posted works fine. thats why you dont use system() [~] $ cat test.cpp*/ #include <stdio.h> #include <stdlib.h> int main() { printf( "One\n" ); system( "echo two" ); printf( "Three\n" ); } /* [~] $ g++ test.cpp [~] $ ./a.out One two Three [~] $ ./a.out | more two One Three */
5th Feb 2021, 2:02 PM
A S Raghuvanshi
A S Raghuvanshi - avatar
+ 4
Arsenic [Part 1] Just a disclaimer. What I say might be insanely dumb because it is just a wild guess. Just saying this because it sounds kinda dumb to me, but it's the best solution I could come up with. So, I tried running 'gcc -v' on Termux (if you don't know, a Linux emulator on Android), and there was a *slight* delay between running the command and getting the output. I couldn't try with 'gcc —version' because gcc is basically an alias for clang in termux and 'gcc -v' and 'gcc —version' give the same result. But, if we take the delay into consideration and *assume*, that 'gcc —version' has a much smaller delay than 'gcc -v', then I think the execution of your code works like this 1. It makes a call to the system to execute 'gcc —version', which immediately appends output to the stdout 2. Then, it makes a call to 'gcc -v'. Now all your program does is make a call to the system and move on. 3. It encounters the cout statement and appends to the stdout
4th Feb 2021, 3:55 PM
XXX
XXX - avatar
+ 4
[Part 2] 4. Encounters another 'gcc —version', same as point 1 5. Another 'gcc -v', same as point 2 6. Another cout statement, same as point 3 7. By this time, the first 'gcc -v' is completed and now that appends to the stdout 8. By this time, the second 'gcc -v' finishes and does the same thing Now, I know system() is blocking. So here comes the dumb part which is my *assumption* that online platforms **fork** processes. So when you execute 'gcc -v', instead of simply executing the process, SoloLearn forks the process which makes it run alongside the execution of the main program. Thus, because 'gcc —version' takes negligible time to complete, its effect is seen as expected and because 'gcc -v' takes more time, its execution finishes after all other processes and the effect is seen at the end (or possibly, after the execution of the program).
4th Feb 2021, 3:56 PM
XXX
XXX - avatar
+ 4
I answered without reading other answers. It's really strange why gcc -v and gcc --version output to stderr and stdout.
5th Feb 2021, 10:37 AM
Sonic
Sonic - avatar
+ 4
This way, you can preserve the output order. https://code.sololearn.com/c0VxdwJCsjQL/?ref=app
5th Feb 2021, 10:48 AM
Sonic
Sonic - avatar
+ 4
💫💫 does the wrong order remain if you do fflush(stdout) after each printf?
5th Feb 2021, 2:10 PM
Volodymyr Chelnokov
Volodymyr Chelnokov - avatar
+ 3
Lily Mea yes that make sense. But even after flushing the buffer before printing system() calls, the output from one command is fixed, but behaviour of other one is still unexplained 👇 https://code.sololearn.com/cO9C3y8oBWZJ/?ref=app I suspect this has something to do with child process( created by system() ) inheriting the buffer of parent process
4th Feb 2021, 12:44 PM
Arsenic
Arsenic - avatar
+ 3
XXX the assumption is correct for both online and ofline platform. This is how system() roughly works :- 1) fork the process ( using fork() ) 2) execute the command in that process ( using execl() ) And now it's starting to come together. 🙂 The fork process finishes the call to "gcc --version" much faster and push the output to stout but as Lily Mea said, cout was loading it in buffer, waiting for buffer to flush or be filled. That's why when I used "endl" to flush it, the first statement appeared before the second call to "gcc --version", meanwhile "gcc -v" is going on slowly in the background making the output display at the end. Thanks both of you for your answers
4th Feb 2021, 4:34 PM
Arsenic
Arsenic - avatar
+ 3
Arsenic One thing I don't understand. You said that system() does the same thing in both online platforms and on offline systems, i.e., fork() and execl(). So if the process is forked in both cases, how is system() on offline systems blocking while on online platforms, it is not?
4th Feb 2021, 5:23 PM
XXX
XXX - avatar
+ 3
By adding endl at the end of the cout (as opposed to or in addition to '\n') you can get cout to immediately flush the buffer and thereby preserve the order of output like so: https://code.sololearn.com/c4ljgba95JVA/?ref=app
5th Feb 2021, 10:27 AM
Sonic
Sonic - avatar
+ 3
By adding "2 >&1" at the end of "gcc -v" you can redirect the gcc output to go to stdout.
5th Feb 2021, 10:44 AM
Sonic
Sonic - avatar
+ 3
💫💫 that's most probably because by default interactive terminals are line buffered means the output is flushed at the end of every line while this doesn't happen when it is piped ( where stream is fully buffered ) Try to flush the buffer before calling the system() (as suggested by Volodymyr Chelnokov ) and check what happens.
5th Feb 2021, 3:03 PM
Arsenic
Arsenic - avatar