1123. No requirement that standard streams be flushed

Section: 31.5.2.2.6 [ios.init] Status: C++11 Submitter: James Kanze Opened: 2009-05-14 Last modified: 2021-06-06

Priority: Not Prioritized

View all other issues in [ios.init].

View all issues with C++11 status.

Discussion:

As currently formulated, the standard doesn't require that there is ever a flush of cout, etc. (This implies, for example, that the classical hello, world program may have no output.) In the current draft (N2798), there is a requirement that the objects be constructed before main, and before the dynamic initialization of any non-local objects defined after the inclusion of <iostream> in the same translation unit. The only requirement that I can find concerning flushing, however, is in [ios::Init], where the destructor of the last std::ios_base::Init object flushes. But there is, as far as I can see, no guarantee that such an object ever exists.

Also, the wording in [iostreams.objects] says that:

The objects are constructed and the associations are established at some time prior to or during the first time an object of class ios_base::Init is constructed, and in any case before the body of main begins execution.

In [ios::Init], however, as an effect of the constructor, it says that

If init_cnt is zero, the function stores the value one in init_cnt, then constructs and initializes the objects cin, cout, cerr, clog wcin, wcout, wcerr, and wclog"

which seems to forbid earlier construction.

(Note that with these changes, the exposition only "static int init_cnt" in ios_base::Init can be dropped.)

Of course, a determined programmer can still inhibit the flush with things like:

new std::ios_base::Init ;       //  never deleted

or (in a function):

std::ios_base::Init ensureConstruction ;
//  ...
exit( EXIT_SUCCESS ) ;

Perhaps some words somewhere to the effect that all std::ios_base::Init objects should have static lifetime would be in order.

[ 2009 Santa Cruz: ]

Moved to Ready. Some editorial changes are expected (in addition to the proposed wording) to remove init_cnt from Init.

Proposed resolution:

Change 31.4 [iostream.objects]/2:

-2- The objects are constructed and the associations are established at some time prior to or during the first time an object of class ios_base::Init is constructed, and in any case before the body of main begins execution.292 The objects are not destroyed during program execution.293 If a translation unit includes <iostream> or explicitly constructs an ios_base::Init object, these stream objects shall be constructed before dynamic initialization of non-local objects defined later in that translation unit. The results of including <iostream> in a translation unit shall be as if <iostream> defined an instance of ios_base::Init with static lifetime. Similarly, the entire program shall behave as if there were at least one instance of ios_base::Init with static lifetime.

Change [ios::Init]/3:

Init();

-3- Effects: Constructs an object of class Init. If init_cnt is zero, the function stores the value one in init_cnt, then constructs and initializes the objects cin, cout, cerr, clog (27.4.1), wcin, wcout, wcerr, and wclog (27.4.2). In any case, the function then adds one to the value stored in init_cnt. Constructs and initializes the objects cin, cout, cerr, clog, wcin, wcout, wcerr and wclog if they have not already been constructed and initialized.

Change [ios::Init]/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, If there are no other instances of the class still in existance, calls cout.flush(), cerr.flush(), clog.flush(), wcout.flush(), wcerr.flush(), wclog.flush().