[comp.lang.c++] cout in static object constructors

lms@uts.amdahl.com (Linda Sorauf) (05/24/91)

I have a question regarding using cout in constructors
of static objects. I hope I can word the question clearly....

Basically, I have been warned against using cout
in constructors of static objects.  Apparently,
cout, which is itself not static, relies on a
static object called iostream_init.  The danger
is that the order of static object construction
may be such that cout is used before iostream_init
has been constructed.

Can someone explain to me
	1) is this even true, should I avoid using
cout in constructors of static objects?
	2) if so, why?
	3) how can I create a test case where this
failure happens?  I have tried every sort of file and 
include arrangements I can think of, but cannot create
such a failure.  I am quite sure that I have been able
to use cout before iostream_init is constructed, but
in my simple programs, things seem to work fine.

Thanks in advance,

Linda Sorauf		lms@uts.amdahl.com
UTS CASE development	Amdahl Corp.
-- 
- - - - - - - - - - - - 
Linda Sorauf		
lms@uts.amdahl.com		
#include <std.disclaim.h>

steve@taumet.com (Stephen Clamage) (05/25/91)

lms@uts.amdahl.com (Linda Sorauf) writes:

>Basically, I have been warned against using cout
>in constructors of static objects.  Apparently,
>cout, which is itself not static, relies on a
>static object called iostream_init.  The danger
>is that the order of static object construction
>may be such that cout is used before iostream_init
>has been constructed.

There is a general problem with constructors of static objects
referring to other objects.  There is no way to guarantee the 
order of such constructors when they occur in different
compilation units.  (No portable way, at least.)

With this in mind, iostreams were carefully designed to guarantee
that the standard streams are all initialized before any user-defined
objects are constructed, PROVIDED that you #include <iostream.h> (or
some file which includes it, such as <fstream.h> or <strstream.h>)
ahead of any static object which needs to use a standard stream.

Example 1 (all in one file) will always work:
	#include <iostream.h>
	class C  {
	public:
	    C();
	    // ...
	};
	C c;
	C::C() { ... cout << "hello\n"; }

Example 2 (all in one file) will compile and link, but may or may not work:
	class C  {
	public:
	    C();
	    // ...
	};
	C c;
	#include <iostream.h>
	C::C() { ... cout << "greetings from C\n"; }

Example 3 (two files) will compile and link, but may or may not work:
    file1.c:
	class C  {
	public:
	    C();
	    // ...
	};
	C c;

    file2.c:
	#include <iostream.h>
	C::C() { ... cout << "greetings from C\n"; }

Examples 2 and 3 will work if by chance cout gets constructed before
the constructor for c gets called.  You cannot in general predict
whether this will happen.

You can make Example 2 work by moving the include to the top of the file.
You can make Example 3 work by including <iostream.h> in file1.c.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

davew@panache.cs.umd.edu (David G. Wonnacott) (05/25/91)

In article <746@taumet.com> steve@taumet.com (Stephen Clamage) writes:
>With this in mind, iostreams were carefully designed to guarantee
>that the standard streams are all initialized before any user-defined
>objects are constructed, PROVIDED that you #include <iostream.h> (or
>some file which includes it, such as <fstream.h> or <strstream.h>)
>ahead of any static object which needs to use a standard stream.

I believe this works with AT&T's iostream library, but not with the
stream library distributed with G++.
--
David Wonnacott
davew@tove.cs.umd.edu

     Although the moon is smaller than the earth, it is further away.