Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Should cout flush on exit?

2 views
Skip to first unread message

Ernest Crvich

unread,
Apr 10, 2000, 3:00:00 AM4/10/00
to
Is there any guarantee or de facto standard such that the cout stream
buffer is flushed when a program terminates normally (return from main()
or exit())? I've tested over a dozen operating systems just out of
curiosity, and only one uses a C++ library that fails to flush cout on
exit. I'm wondering whether this is worth trying to get "fixed", or if
it's just a part of life.

--
Ernest M. Crvich
IBM ODE Team
Have footbag, will shred.

Ernest Crvich

unread,
Apr 11, 2000, 3:00:00 AM4/11/00
to

Chris Double

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to
Ernest Crvich <crv...@us.ibm.com> writes:

> I'm wondering whether this is worth trying to get "fixed", or if
> it's just a part of life.

I think Be should fix it. It would seem to be a trivial fix and it
would prevent a *lot* of questions about why people aren't getting
output in their programs on comp.sys.be.programmer. This has tripped
up quite a few people in the past.

Chris.
--
http://www.double.co.nz/beos

Homer Meyer

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to

Ernest Crvich wrote in message <38F347DD...@us.ibm.com>...

>Is there any guarantee or de facto standard such that the cout stream
>buffer is flushed when a program terminates normally (return from main()
>or exit())? I've tested over a dozen operating systems just out of
>curiosity, and only one uses a C++ library that fails to flush cout on
>exit. I'm wondering whether this is worth trying to get "fixed", or if

>it's just a part of life.


You do realize that calling exit() isn't a normal exit? The exit() function
does does cleanup in C code, but being a C library function, it knows
nothing about C++ destructors and classes. Call it at your own risk.

When you return from main(), cout's destructor is called and the output is
flushed, but this may or may not happen with exit(). I would suspect that
in most cases exit() will abort your program without calling any
destructors. From what you are seeing, it might be that the destructors for
globals are getting called when you call exit(), but this is not guaranteed,
and I would suspect that destructors for your auto variables are not getting
called. At any rate calling exit() in a C++ program is dangerous. Do it at
your own risk.

If you want a safe exit style function in C++, throw an exception and catch
it in a handler in main().

Homer

comp.lang.c++ links:
Welcome: http://www.slack.net/~shiva/welcome.txt
FAQ: http://marshall-cline.home.att.net/cpp-faq-lite/

Pete Becker

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to
Homer Meyer wrote:
>
> Ernest Crvich wrote in message <38F347DD...@us.ibm.com>...
> >Is there any guarantee or de facto standard such that the cout stream
> >buffer is flushed when a program terminates normally (return from main()
> >or exit())? I've tested over a dozen operating systems just out of
> >curiosity, and only one uses a C++ library that fails to flush cout on
> >exit. I'm wondering whether this is worth trying to get "fixed", or if
> >it's just a part of life.
>
> You do realize that calling exit() isn't a normal exit? The exit() function
> does does cleanup in C code, but being a C library function, it knows
> nothing about C++ destructors and classes. Call it at your own risk.
>

The C++ standard requires destructors to be run when a program calls
exit.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Contibuting Editor, C/C++ Users Journal (http://www.cuj.com)

Michael Rubenstein

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to
On Wed, 12 Apr 2000 23:27:34 GMT, Pete Becker
<peteb...@acm.org> wrote:

>Homer Meyer wrote:
>>
>> Ernest Crvich wrote in message <38F347DD...@us.ibm.com>...
>> >Is there any guarantee or de facto standard such that the cout stream
>> >buffer is flushed when a program terminates normally (return from main()
>> >or exit())? I've tested over a dozen operating systems just out of
>> >curiosity, and only one uses a C++ library that fails to flush cout on
>> >exit. I'm wondering whether this is worth trying to get "fixed", or if
>> >it's just a part of life.
>>
>> You do realize that calling exit() isn't a normal exit? The exit() function
>> does does cleanup in C code, but being a C library function, it knows
>> nothing about C++ destructors and classes. Call it at your own risk.
>>
>
>The C++ standard requires destructors to be run when a program calls
>exit.

Clarification: The standard requires destructors of staticly
allocated objects to be run when a program calls exit. Since
cout is such an object, Pete's point is valid.

Dima Volodin

unread,
Apr 12, 2000, 3:00:00 AM4/12/00
to
Pete Becker wrote:
>
> Homer Meyer wrote:
> >
> > Ernest Crvich wrote in message <38F347DD...@us.ibm.com>...
> > >Is there any guarantee or de facto standard such that the cout stream
> > >buffer is flushed when a program terminates normally (return from main()
> > >or exit())? I've tested over a dozen operating systems just out of
> > >curiosity, and only one uses a C++ library that fails to flush cout on
> > >exit. I'm wondering whether this is worth trying to get "fixed", or if
> > >it's just a part of life.
> >
> > You do realize that calling exit() isn't a normal exit? The exit() function
> > does does cleanup in C code, but being a C library function, it knows
> > nothing about C++ destructors and classes. Call it at your own risk.
> >
>
> The C++ standard requires destructors to be run when a program calls
> exit.

It depends on what objects you are talking about. See 3.6.1/4 and
3.6.3/1.

> Pete Becker


> Contibuting Editor, C/C++ Users Journal (http://www.cuj.com)

Dima

Pete Becker

unread,
Apr 13, 2000, 3:00:00 AM4/13/00
to
Michael Rubenstein wrote:
>
> On Wed, 12 Apr 2000 23:27:34 GMT, Pete Becker
> <peteb...@acm.org> wrote:
>
> >The C++ standard requires destructors to be run when a program calls
> >exit.
>
> Clarification: The standard requires destructors of staticly
> allocated objects to be run when a program calls exit. Since
> cout is such an object, Pete's point is valid.

Yes, thanks for straightening that out. This just hasn't been my day.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

Chris Double

unread,
Apr 13, 2000, 3:00:00 AM4/13/00
to
"Homer Meyer" <ho...@cqg.com> writes:

>
> You do realize that calling exit() isn't a normal exit? The exit() function
> does does cleanup in C code, but being a C library function, it knows
> nothing about C++ destructors and classes. Call it at your own
> risk.

On the particular platform that the original poster was talking about
(I'm thinking it was BeOS since the problem occurs in BeOS), cout is
not flushed on normal return from main. I think this is what the
original poster was talking about when he said 'exit' not the function
'exit'.

Chris.
--
http://www.double.co.nz/beos

Dietmar Kuehl

unread,
Apr 13, 2000, 3:00:00 AM4/13/00
to
Hi,
In article <698afs483qpi2i9te...@4ax.com>,

Michael Rubenstein <mik...@ix.netcom.com> wrote:
> Clarification: The standard requires destructors of staticly
> allocated objects to be run when a program calls exit. Since
> cout is such an object, Pete's point is valid.

Interesting... How does this agree with this statement from 27.3,
lib.iostream.objects, paragraph 2?

The objects are not destroyed during program execution.

where "The objects" refers to the standard stream objects 'std::cout',
'std::cin', ... This is clear from the context.

However, this statement has not implications on the standard stream
objects being flushed because this is achieved by the destructor of
'std::ios_base::Init' (27.4.2.1.6, lib.ios::Init, paragraph 4):

~Init();

-4- Effects: Destroys an object of class Init. The function subtracts
one from the value stored in init_cnt and, if the resulting
stored value is one, calls cout.flush(), cerr.flush(), clog.flush(),
wcout.flush(), wcerr.flush(), wclog.flush().

But then, I'm not sure that an implementation is required to allocate
an object of this type: I haven't found any such requirement. I think
an implementation is allowed to avoid the construction of an 'Init'
object if it can do without one and this is clearly possible. Here are
some possibilities:

- The standard stream objects can be made operational with zero
initialization although this would incur extra costs during normal
use of all stream objects. Since zero initialization is done first
this is a safe way.

- Putting the stream objects into a separate dynamically linked object
can assure initialization of the objects when they are first accessed
if the dynamic loader of the system executes some special code when
loading a dynamically linked object. Since the dynamically linked
object has to be loaded before the streams can be accessed, this
makes sure they are initialized before they are used. The only tricky
thing is the additional requirement that these streams are
initialized prior to 'main()' (if they are used at all, that is) but
even this can be made sure by hacking the start up code to touch the
standard stream object before executing the actual 'main()'.

- On many systems it is possible to rely on a linking order depending
on the placement of the object files in a library: For example, on
some systems the objects seen last are initialized first. Since the
linker is under the control of the implementation, the implementation
can indeed rely on such features and arrange for correct
initialization of the stream objects without using 'Init'.

Since the use of 'std::ios_base::Init' in headers is rather costly,
implementations are likely to avoid it's construction. Correspondingly,
these objects aer also never destructed and thus the standard streams
are never flushed since they are never destructed. I think the standard
library is *NOT* required to flush the standard stream objects unless
it constructs an 'std::ios_base::Init' object. However, I would expect
that all implementations still flush the standard stream objects!
--
<mailto:dietma...@claas-solutions.de>
homepage: <http://www.informatik.uni-konstanz.de/~kuehl>


Sent via Deja.com http://www.deja.com/
Before you buy.

Ernest Crvich

unread,
Apr 14, 2000, 3:00:00 AM4/14/00
to
In article <8d4id1$bm4$1...@nnrp1.deja.com>, Dietmar Kuehl <dietma...@claas-solutions.de> wrote:
>are never flushed since they are never destructed. I think the standard
>library is *NOT* required to flush the standard stream objects unless
>it constructs an 'std::ios_base::Init' object. However, I would expect
>that all implementations still flush the standard stream objects!

So it's the de facto standard, which is sort of what I expected (without
knowing exactly why). The GNU (as tested on Linux, NetBSD, FreeBSD, OpenBSD,
Solaris, etc.), IBM (AIX, OS/2), Microsoft, Sun, HP, and SCO C++ libraries
all flush cout, but the BeOS (based on GNU, I presume, since gcc is the
supplied compiler) library does not (at least on 4.5, I haven't tried 5.0
yet). I figured they weren't forced to conform, but I'm still trying to
persuade them to do so.

Dietmar Kuehl

unread,
Apr 14, 2000, 3:00:00 AM4/14/00
to crv...@raleigh.ibm.com
Hi,
In article <8d82ub$1ltq$1...@news2atm.raleigh.ibm.com>,

crv...@raleigh.ibm.com (Ernest Crvich) wrote:
> I figured they weren't forced to conform, but I'm still trying to
> persuade them to do so.

Like I showed, I think the current status is that an implementation is
not required to flush the standard stream objects. Maybe I find
interested parties next week on the standards meeting to discuss this
state of affairs. However, it is easy for a user to arrange that the
standard stream objects are flushed. Just add a static
'std::ios_base::Init' object to the module containing the 'main()'
function:

#include <ios>
static std::ios_base::Init flush_dummy;
int main() {
// ...
}

Of course, it would be nice if the implementation did that for you but
than it is not that hard to do it yourself. If the implementation
flushed the standard stream objects, it does no harm (except
potentially changing the exact time when the objects are flushed) and
if the implementation does not, this will flush the standard stream
objects, at least if static objects are destructed correctly. However,
the implementation is required to destruct these objects...

0 new messages