Title
basic_ios::set_rdbuf may break class invariants
Status
c++11
Section
[basic.ios.members]
Submitter
Daniel Krügler

Created on 2009-07-28.00:00:00 last changed 162 months ago

Messages

Date: 2011-04-30.23:09:42

Rationale:

We believe that setting a nullptr stream buffer can be prevented.

Date: 2010-11-24.14:01:03

Proposed resolution:

  1. Add a new pre-condition just before 27.5.4.2 [basic.ios.members]/23 as indicated:
    void set_rdbuf(basic_streambuf<charT, traits>* sb);
    

    ?? Requires: sb != nullptr.

    23 Effects: Associates the basic_streambuf object pointed to by sb with this stream without calling clear().

    24 Postconditions: rdbuf() == sb.

    25 Throws: Nothing.

Date: 2010-11-24.14:01:03

[ Adopted at 2010-11 Batavia ]

Date: 2010-10-21.19:06:53

[ Post-Rapperswil ]

Several reviewers and the submitter believe that the best solution would be to add a pre-condition that the buffer shall not be a null pointer value.

Moved to Tentatively Ready with revised wording provided by Daniel after 5 positive votes on c++std-lib.

Date: 2009-10-20.00:00:00

[ 2009-10-20 Martin provides wording: ]

Change [basic.ios.members] around p. 19 as indicated:

void set_rdbuf(basic_streambuf<charT, traits>* sb);

Effects: Associates the basic_streambuf object pointed to by sb with this stream without calling clear(). Postconditions: rdbuf() == sb.

Effects: As if:


iostate state = rdstate();
try { rdbuf(sb); }
catch(ios_base::failure) {
   if (0 == (state & ios_base::badbit))
       unsetf(badbit);
}

Throws: Nothing.

We need to be able to call set_rdbuf() on stream objects for which (rdbuf() == 0) holds without causing ios_base::failure to be thrown. We also don't want badbit to be set as a result of setting rdbuf() to 0 if it wasn't set before the call. This changed Effects clause maintains the current behavior (as of N2914) without requiring that sb be non-null.

Date: 2010-10-21.18:28:33

[ 2009-10 Santa Cruz: ]

Moved to Open. Martin volunteers to provide new wording, where set_rdbuf() sets the badbit but does not cause an exception to be thrown like a call to clear() would.

Date: 2009-07-28.00:00:00

The protected member function set_rdbuf had been added during the process of adding move and swap semantics to IO classes. A relevant property of this function is described by it's effects in [basic.ios.members]/19:

Effects: Associates the basic_streambuf object pointed to by sb with this stream without calling clear().

This means that implementors of or those who derive from existing IO classes could cause an internal state where the stream buffer could be 0, but the IO class has the state good(). This would break several currently existing implementations which rely on the fact that setting a stream buffer via the currently only ways, i.e. either by calling

void init(basic_streambuf<charT,traits>* sb);

or by calling

basic_streambuf<charT,traits>* rdbuf(basic_streambuf<charT,traits>* sb);

to set rdstate() to badbit, if the buffer is 0. This has the effect that many internal functions can simply check rdstate() instead of rdbuf() for being 0.

I therefore suggest that a requirement is added for callers of set_rdbuf to set a non-0 value.

History
Date User Action Args
2011-08-23 20:07:26adminsetstatus: wp -> c++11
2010-11-24 14:01:03adminsetmessages: + msg5418
2010-11-14 13:10:57adminsetstatus: voting -> wp
2010-11-08 14:14:39adminsetstatus: ready -> voting
2010-10-21 19:06:53adminsetmessages: + msg4763
2010-10-21 19:06:53adminsetstatus: open -> ready
2010-10-21 18:28:33adminsetmessages: + msg1054
2010-10-21 18:28:33adminsetmessages: + msg1053
2010-10-21 18:28:33adminsetmessages: + msg1052
2010-10-21 18:28:33adminsetmessages: + msg1051
2009-07-28 00:00:00admincreate