Possible bug in libstdc++ 2.90.8
Benjamin Kosnik
bkoz@redhat.com
Tue Aug 15 11:42:00 GMT 2000
Hi Maurizio.
> 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.
... just use the public methods, pubsync() instead. Pretty
straightforward bug fix....
> 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.
... also a bit of type non-standardization, which I fixed in the edited
copy of your code below. The edited code works correctly for me with CVS
libstdc++-v3,.
> 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 :-(
? Seems to work for me. Can you provide more detail?
thanks,
benjamin
// 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.
#if 0
int overflow(int); // Pure virtual methods inherited
int underflow(); // from streambuf that we must
int uflow(); // define in our code.
int sync();
#else
// 2000-08-15 bkoz
// These methods have different signatures.
// 27.5.2 basic_streambuf
int_type overflow(int_type);
int_type underflow();
int_type uflow();
int sync();
#endif
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, streambuf *l)
: streambuf(), scr_sb_(s), log_sb_(l), log_(true)
{
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.
mySbuf::int_type mySbuf::underflow()
{
throw runtime_error("Can't happen (underflow)");
}
mySbuf::int_type 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().
mySbuf::int_type mySbuf::overflow(int_type 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()
{
#if 0
scr_sb_->sync();
log_sb_->sync();
#else
// 2000-08-15 bkoz
// use the public methods...
scr_sb_->pubsync();
log_sb_->pubsync();
#endif
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;
}
}
More information about the Libstdc++
mailing list