This discussion is archived
3 Replies Latest reply: Nov 30, 2011 2:07 AM by 902766 RSS

Getting bad state on custom stream only when using SolStudio

800173 Newbie
Currently Being Moderated
Running the code below on linux returns a "good" iostate, when compiling with SS11 or SS12.2 this code returns "bad" iostate. We'd like to understand what the base class (std::ios_base) is doing in the contructor. It appears to be related to the existence of a member variable (int foo). If you remove this variable (via if 0) then it works as expected:


//////////////////////////////////////////////////////////////////////////////
//
// Test sample code to illustrate an apparent problem with SunStudio 11/12
//
// The problem appears as a bad state on a custom stream, after construction.
// The construction sequence has been confirmed on other platforms.
//
// The problem appears to be triggered by the definition of a member variable
// in the derived stream buffer class. If the variable is defined, even if it
// isn't referenced in the constructor, the stream class is marked as 'bad'.
//
//
//////////////////////////////////////////////////////////////////////////////


#include <iostream>
#include <iosfwd>
#include <sstream>


// Custom Stream Buffer
class mybuf : public std::stringbuf
{
typedef std::stringbuf tBase;

public:
mybuf() : tBase()
{
; // For setting a breakpoint
}

virtual ~mybuf() { }

private:
// The existence of this variable in the class appears to trigger the problem.
// Note: The variable doesn't even have to be initialized in the constructor.
#if 1
int               foo;
#endif
};



// Custom Stream Buffer
class mystream
: public std::basic_ostream<char, std::char_traits<char> >
{
public:
typedef char tElem;
typedef std::char_traits<char> tTraits;
typedef std::basic_ostream<tElem, tTraits> tBase;
typedef mybuf tBuffer;


explicit mystream() : tBase(&m_buffer)
{
; // For setting a breakpoint
     }
virtual ~mystream() { }

private:
tBuffer m_buffer;
};



int
main(int argc, char **argv)
{
int retVal = 0;
mystream filestream;

std::ios_base::iostate nInitState = filestream.rdstate();
std::cerr << "INFO: Initial Input Stream state is: \""
<< std::hex << (int) nInitState << std::dec << "\"" << std::endl;
if(!filestream.good())
{
std::ios_base::iostate nInitState = filestream.rdstate();
std::cerr << "ERROR: Initial Input Stream state is NOT in GOOD state!" << std::endl;
retVal = -1;
}

return retVal;
}


thanks
  • 1. Re: Getting bad state on custom stream only when using SolStudio
    Steve_Clamage Pro
    Currently Being Moderated
    I don't see anything obviously wrong with your code, so you appear to have run into an issue with the default libCstd used with the compiler. The optional STLport library fails with a runtime abort, but the optional Apache stdcxx library (available on Solaris 10u10 and Solaris 11) does not have a problem.

    If you have a service contract with Oracle, please file a bug report via your support channel. Otherwise, please file a bug report at http://bugs.sun.com

    BTW, please use "code" tags when posting source code, scripts, or compiler output. The tags preserve the code format, and prevent the Forum software from interpreting special characters as formatting directives.
  • 2. Re: Getting bad state on custom stream only when using SolStudio
    800173 Newbie
    Currently Being Moderated
    Thanks Steve - I'll file it with support. Thanks for the heads up on the tags...
  • 3. Re: Getting bad state on custom stream only when using SolStudio
    902766 Newbie
    Currently Being Moderated
    The standard says:
    27.4.4.1 pt. 3
    postconditions of <tt>basic_ios::init(basic_streambuf* sb)</tt>
    <tt>rdbuf()</tt> == sb
    ...
    <tt>rdstate()</tt> == <tt>goodbit</tt> if sb is not a null pointer, otherwise <tt>badbit</tt>

    27.6.2.2
    <tt>basic_ostream::basic_ostream(basic_streambuf* sb)</tt> constructs an object of class <tt>basic_ostream</tt>, assigning initial values to the base class by calling <tt>basic_ios::init(</tt>sb<tt>)</tt>
    postcondition: <tt>rdbuf() == </tt>sb
    The implementation from libCstd sets <tt>badbit</tt> and <tt>rdbuf() == 0</tt> (check that, add <tt><< static_cast<void*>(filestream.rdbuf())</tt>). This is because <tt>basic_ostream</tt> constructor checks if sb has the mode bit <tt>ios_base::out</tt> set and installs null buffer if it is cleared.

    This is not standard-conformant but helped find a real problem with your code (this is not 100% libCstd fault). Its behaviour is definitely not well defined:

    <tt>mystream</tt> constructor provides the base class with an not yet initialized <tt>m_buffer</tt>. This is because base class (<tt>basic_ostream</tt>) constructor gets called before <tt>m_buffer</tt>'s constructor. So the <tt>mode_</tt> member of <tt>m_buffer</tt> tested in <tt>basic_ostream</tt> constructor has yet undefined value which happens to have <tt>ios_base::out</tt> bit set when <tt>foo</tt> is excluded and cleared otherwise.

    I cannot figure out how the <tt>foo</tt> member influences initial (i.e. not-yet-constructed) value of <tt>mode_</tt> member of the buffer

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points