Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

About stdout/stderr redirections

Tags:

c

bash

I wrote a code to get a runtime error intentionally:

int main()
{
 int a=5;
 printf("Hello World\n");
 printf("a=%s\n", a);
}

It gives:

$ ./error.o
Hello World
Segmentation Fault
$

Now, to record the runtime errors, I do:

$ ./error.o > so.txt
$ ./error.o &> soe.txt

But both the files are empty. Why?

EDIT:

I'm actually writing a script for remote compilation and execution of a c program. From the answers I get that Segmentation Fault is not the program's error output. So, is there a way to capture that output? Also, the program is just a sample, so I can't add the statements. Can line-buffering be done any other way with redirections?

like image 850
lalli Avatar asked Oct 29 '10 08:10

lalli


3 Answers

so.txt is empty because stdout didn't get flushed before the crash so the buffered content was lost. If you add: fflush(stdout); between the printf-commands, it will contain the expected text.

Your soe.txt is missing also the the message "Segmentation Fault" because it was printed by the shell, not by your program and thus wasn't part of your program's output that was to be redirected.

If you can't modify the code, you can turn on line buffering by fooling the program to think it's printing to a tty. Create the script error.sh:

#!/bin/sh
./error.o

Then do chmod a+x error.sh and call it like this on Linux:

script soe.txt -c ./error.sh

Or like this on OS X:

script soe.txt ./error.sh

The exact output is somewhat system-dependent but will probably contain both "Hello World" and "Segmentation Fault".

Also consider adding appropriate #include lines and returning a value from main.

like image 150
jjrv Avatar answered Nov 12 '22 06:11

jjrv


Because a segmentation fault is serious. Buffers don't get flushed, your process just gets shut down violently.

The reason you see the text when you run without redirection is that standard output is line buffered (ISO C mandates that full buffering is used only if the device can be determined not to be an interactive one). In other words, it will flush whenever it sees a newline, and that happens before your invalid de-referencing.

But because the file output is not line-buffered, the information is still waiting to be sent out when your program's universe is yanked out from under it.

Although support for this is implementation-defined, you can set a specific file handle to be line buffered by using setvbuf with the _IOLBF mode, something like:

setvbuf (stdout, NULL, _IOLBF, BUFSIZ);

at the start of main() - it saves a substantial amount of typing over having to fflush every output line.

like image 35
paxdiablo Avatar answered Nov 12 '22 07:11

paxdiablo


I think this should do it:

echo ./error.o | sh > error.txt
like image 3
fortran Avatar answered Nov 12 '22 07:11

fortran