[LLVMdev] Different behavoir when writing to stdout with 2 raw_fd_ostreams with or w/o redirection

Dmitry N. Mikushin maemarcus at gmail.com
Thu Nov 29 11:03:50 PST 2012


Hi Dan, Sean,

Thanks for replies,

So does it mean user is not expected to use any other stream for stdout,
but outs()? Although there is a comment "If you don't want this behavior,
don't use outs().", outs() is a static instance which always exists and
creates problems, even if not used.

- D.

2012/11/29 Dan Gohman <dan433584 at gmail.com>

> On Wed, Nov 28, 2012 at 10:54 PM, Dmitry N. Mikushin <maemarcus at gmail.com>wrote:
>
>> Dear all,
>>
>> Consider there is a program that writes to stdout using two different
>> raw_fd_ostream-s:
>
>
> raw_fd_ostream does buffered I/O, so it's not really meant to be used like
> this.
>
>
>> #include "llvm/LLVMContext.h"
>> #include "llvm/Module.h"
>> #include "llvm/Support/raw_ostream.h"
>>
>> using namespace llvm;
>>
>> int main()
>> {
>>         raw_fd_ostream S(STDOUT_FILENO, false);
>>
>>         outs() << "Hello";
>>         S << ", world!";
>>
>>         return 0;
>> }
>>
>> With this layout everything is fine, it prints ", world!Hello"
>>
>
> Yes. raw_ostream does buffering. The output you see is a classic symptom
> of having two different buffers for the same file descriptor. You can make
> this work by manually flushing when switching from one buffer to another,
> if you're careful.
>
>
>>
>> Now, make S definition global:
>>
>> #include "llvm/LLVMContext.h"
>> #include "llvm/Module.h"
>> #include "llvm/Support/raw_ostream.h"
>>
>> using namespace llvm;
>>
>> raw_fd_ostream S(STDOUT_FILENO, false);
>>
>> int main()
>> {
>>         outs() << "Hello";
>>         S << ", world!";
>>
>>         return 0;
>> }
>>
>> And... surprisingly:
>>
>> $ ./outs
>> Hello, world!$ ./outs &>result
>> $ cat result
>> HelloLLVM ERROR: IO failure on output stream.
>>
>> So, no error with screen output and error when redirected to file. Why so?
>
>
> The difference in output is due to the difference in when the buffers
> happen to get destructed, because they flush their buffers in their
> destructors.
>
> The error comes from the fact that outs() closes STDOUT_FILENO when the
> program exits. Your other raw_fd_ostream is getting unlucky and having its
> destructor run after the outs() object is destructed, so it ends up trying
> to write to a closed file descriptor. There's no easy way to avoid this
> problem, as global destructor ordering is inconvenient to control. In
> general, it's best to try to avoid this situation altogether.
>
> Dan
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20121129/9d389b1e/attachment.html>


More information about the llvm-dev mailing list