[comp.sys.ibm.pc] Turbo C 1.5 setbuf

ado@elsie.UUCP (Arthur David Olson) (02/17/88)

Repeat-By:
	Compiling and running this source

		#include "stdio.h"

		main()
		{
			static char	buf[BUFSIZ];

			setbuf(stderr, buf);
			(void) fprintf(stderr, "byebye\n");
			return 0;
		}

	and noting the lack of output.

Setvbuf messes up as well.

All goes well if you subsitute "stdout" for "stderr" above.

A workaround is an early "atexit" call specifying a function
that does a fflush(stderr).

Fixes, anyone?
-- 
ado@vax2.nlm.nih.gov		ADO, VAX, and NIH are Ampex and DEC trademarks

richardh@killer.UUCP (Richard Hargrove) (02/21/88)

In article <8015@elsie.UUCP>, ado@elsie.UUCP (Arthur David Olson) writes:
> [ code example purporting to demonstrate how calling setbuf() does not
>   cause stderr to actually become buffered ]
> 
> Setvbuf messes up as well.

Not if invoked correctly. See below.

> 
> All goes well if you subsitute "stdout" for "stderr" above.
> 
> A workaround is an early "atexit" call specifying a function
> that does a fflush(stderr).
> 
> Fixes, anyone?

No fix is required because nothing is broken.

Your code example makes the assumption that buffering means line-buffering.
This is true for stdout, which, even though not initially buffered, has the
line-buffering flag (_F_LBUF - see stdio.h) set. Therefore when you associate 
a buffer with it via a call to setbuf(), it is line-buffered and will flush
the buffer everytime a newline is output. This is NOT the case with stderr. 
Since the line-buffering flag is not set, the call to setbuf() causes it to go 
from being unbuffered to full-buffered. Full-buffering means that the buffer 
contents are output only when the buffer has been filled, which your example 
fails to do. Until the buffer is filled, only an explicit call to fflush()
will cause the contents of the buffer to be output.

To accomplish your goal use:

	if (setvbuf (stderr, buf, _IOLBF, BUFSIZ) != 0) {
	  /* handle setvbuf() failure */
	}

This establishes line-buffering as the buffering discipline (you can verify
that _F_LBUF is set). 

While I'll admit that the Turbo C documentation does not spell out all of the
above, it seems to be based on the assumption that if you are playing 
around with the file buffering, the concepts discussed are already at least
partially understood.

To test the above, compile and execute:

#include <stdio.h>
main(void)
{
	static char mybuf[BUFSIZ];

	if (setvbuf (stderr, mybuf, _IOLBF, BUFSIZ) == 0) {
	  fputs ("Does it work yet?\n", stderr);
	}
	else {
	  fputs ("setvbuf() error\n", stdout);
	}
	return 0;
}

I tested all of the above using Turbo C 1.5; I did not verify its accuracy
for version 1.0.

richard hargrove
...!{ihnp4 | codas | cbosgd}!killer!richardh
--------------------------------------------

ado@elsie.UUCP (Arthur David Olson) (02/23/88)

In an earlier article I wrote of a "Turbo C 1.5 setbuf(stderr bug":
< Repeat-By:
< 	Compiling and running this source
< 		#include "stdio.h"
< 		main()
< 		{
< 			static char	buf[BUFSIZ];
< 			setbuf(stderr, buf);
< 			(void) fprintf(stderr, "byebye\n");
< 			return 0;
< 		}
< 	and noting the lack of output.

In article <3433@killer.UUCP>, richardh@killer.UUCP (Richard Hargrove) writes:
< In article <8015@elsie.UUCP>, ado@elsie.UUCP (Arthur David Olson) writes:
< < [ code example purporting to demonstrate how calling setbuf() does not
< <   cause stderr to actually become buffered ]
< 
< . . .with stderr [s]ince the line-buffering flag is not set, the call to
< setbuf() causes it to go from being unbuffered to full-buffered.
< Full-buffering means that the buffer contents are output only when the
< buffer has been filled, which your example fails to do. Until the buffer
< is filled, only an explicit call to fflush() will cause the contents of the
< buffer to be output. . .

Regardless of buffering, the contents of the buffer should be output when
the program exits.  And yet no output appears when I compile and run the
source in my original article.  That's the bug--not whether the setbuf call
causes "stderr to actually become buffered."
-- 
ado@vax2.nlm.nih.gov		ADO, VAX, and NIH are Ampex and DEC trademarks