This is the mail archive of the libstdc++@sources.redhat.com mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Possible bug in libstdc++ 2.90.8


Hello -
I am using libstdc++ 2.90.8 together with g++ 2.95.2 .  I have problems
with my code, because a class that I define inherits from streambuf and
cannot call streambuf::sync(); streambuf's sync() is inherited from
basic_streambuf's sync() that is declared 'protected' and cannot be called
from a class derived from a derived class.

A simplified version of the code I am using is in the attachment; the code
itself compiles and links with Kuck and Associates Inc. (KAI) KCC compiler
after having substituted a couple of int with unsigned int in the
procedure declaration.

The code I am using has been discussed on comp.lang.c++.moderated and
derives by widely used examples by Dietmar Kuehl, that may be found under
http://www.informatik.uni-konstanz.de/~kuehl/ .

I am also (dis)pleased to announce that the perl script at
http://sources.redhat.com/ to submit bug reports does not work for me :-(

Thank you for your work!

-- 
Maurizio Loreti                         http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            loreti@pd.infn.it
// This toy example (based on code written under the GNU GPL by
// Dietmar Kuehl, http://www.informatik.uni-konstanz.de/~kuehl/) shows
// how to define an ostream-like class in such a way that everything
// that will be written to the stream goes both to the standard output
// and to a disk log file.

#include <iostream>
#include <fstream>
#include <stdexcept>

using namespace std;

// The important part of this file is a class mySbuf, derived from the
// class streambuf defined in <iostream>; streambuf defines an
// interface used by [i/o]streams to read bytes from an external
// representation and to write bytes to an external representation.
// The actual handling of the external representation is implemented
// in classes derived from streambuf; in our case the "external
// representation" is a wrapper class that will send every received
// byte to two streams (only _output_ streams are considered).  An
// internal flag allows to inhibit output to the log file; methods to
// access and modify that flag are provided.

class mySbuf : public streambuf {
private:
  streambuf *scr_sb_;           // The streambuf associated with cout;
  streambuf *log_sb_;           //   the one associated with the log file;
  bool       log_;              //     a flag to inhibit log file writing.

  int overflow(int);            // Pure virtual methods inherited
  int underflow();              //   from streambuf that we must
  int uflow();                  //     define in our code.
  int sync();

public:
  mySbuf(streambuf *s, streambuf *l);
  ~mySbuf() {}
  void closeLog() { log_ = false; }
  void openLog() { log_ = true; }
  bool getLog() const { return log_; }
};

// To provide convenient access to the class mySbuf there is an
// ostream-like class logOut provided: that creates a mySbuf with the
// given arguments and initializes its base class (the ostream) with
// this object.  logOut also take care that the allocated mySbuf is
// destructed when the ostream is destructed.

class logOut : public ostream {
public:
  logOut(streambuf *s, streambuf *l) : ostream(new mySbuf(s, l)) {}
  ~logOut() { delete rdbuf(); }
  void closeLog() { dynamic_cast<mySbuf *>(rdbuf())->closeLog(); }
  void openLog() { dynamic_cast<mySbuf *>(rdbuf())->openLog(); }
  bool getLog() const { return dynamic_cast<mySbuf *>(rdbuf())->getLog(); }
};

// The constructor of the class mySbuf initializes its pointers to the
// two streambuf's (for the screen and the log file) with the two
// arguments: it is assumed that these streambuf's are initialized
// correctly.  In addition, no ownership is assumed for these
// streambuf's: they are not deleted in the destructor.  In the body
// of the constructor, the put area and the get area are initialized
// to be empty: no buffering is done by this streambuf, and all
// buffering is deferred to the actually used streambuf.  This makes
// sure that the function overflow() is called whenever a character is
// written to this streambuf, and that the function underflow() or
// uflow() is called whenever a character is read (this is actually
// impossible because we will do output only).  The put buffer is
// specified using streambuf::setp(), and the get buffer is specified
// using streambuf::setg().

mySbuf::mySbuf(
  streambuf *s,                 // The "screen" streambuf,
  streambuf *l                  //   and the "log file" streambuf.
) : streambuf(),
    scr_sb_(s),
    log_sb_(l),
    log_(true)                  // Default: file logging initially enabled
{
  setp(0, 0);
  setg(0, 0, 0);
}

// underflow() should make the next character available for an input
// streambuf; uflow() is similar, but reads past the current
// character.  They are not actually implemented, but throw an
// exception if called.

int mySbuf::underflow()
{
  throw runtime_error("Can't happen (underflow)");
}

int mySbuf::uflow()
{
  throw runtime_error("Can't happen (uflow)");
}

// The function overflow() is concerned with the overflow of the put
// buffer: this function is called with the next character to be put
// into the stream if no more positions are available in the put area.
// Since the put area is empty for our class mySbuf, this function is
// always called if another character is to be put into the stream.
// The operation of overflow() is simple: if some other character than
// EOF is to be put into the stream, this character is put both into
// the "screen" streambuf and the "log file" streambuf using the
// method streambuf::sputc().

int mySbuf::overflow(
  int c
) {
  if (c == EOF) return 0;

  int rc = scr_sb_->sputc(c);
  if (log_) log_sb_->sputc(c);
  return rc;
}

// mySbuf uses sync() to bring the internal representation into
// synchronization with the external representation.  Since a mySbuf
// has no internal representation other than the used streambuf, all
// which has to be done is to call sync() for the used streambuf.

int mySbuf::sync()
{
  scr_sb_->sync();
  log_sb_->sync();
  return 0;
}

// The test program.  Opens a file called "logfile.txt" and outputs
// three lines of shit to the screen (two of them go to the log file
// too).

#include <ctime>

int main() {
  const time_t now( time(0) );
  const unsigned int weekDays = 7;
  ofstream log("logfile.txt");
  if (log) {
    logOut lo(cout.rdbuf(), log.rdbuf());
    lo << "Hi, MLO;";
    lo << ' ' << "how are you ?" << endl;
    lo.closeLog();
    lo << "In a week there are " << weekDays << " days\n";
    lo.openLog();
    lo << "Now is " << asctime(localtime(&now));
    return 0;
  } else {
    cerr << "Couldn't open log file\n";
    return EXIT_FAILURE;
  }
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]