Topic: A few questions regarding stream buffers


Author: James Kanze <kanze@gabi-soft.de>
Date: Thu, 8 Mar 2001 23:55:45 GMT
Raw View
kavdeiv@mail.ru (\"                                  \") writes:

|>  Given an object sbuf of a type derived from streambuf, is it
|>  guaranteed that there is no possibility of me getting exceptions
|>  when reading the contents of the streambuf by means of the following
|>  construct:

|>  istreambuf_iterator<char,char_traits<char> >  begin(&sbuf),  end;

|>  I think that I'm guaranteed not to get any exceptions because
|>  istreambuf_iterators use members sbumpc and sgetc of the underlying
|>  stream buffer, which in turn may call underflow, and the Standard
|>  says that basic_streambuf::underflow can only report an error
|>  condition through returning traits::eof().

What makes you say that?  The standard clearly says (17.4.4.8/3) that
"Any other functions [than a destructor] defined in the C++ standard
library that do not have an exception-specification may throw
implementation-defined exceptions unless otherwise specified."  None of
the functions you speak of have exception specifications, so they may
throw anything.

|>  Am I right? Does it also mean that even if the streambuf object sbuf
|>  referrs to a filestream and the following is held:

|>  has_facet<codecvt<char,char,char_traits<char>::state_type> >(sbuf.getloc()) == false

|>  I still have underflow return traits::eof() without any possibility
|>  for bad_cast?

No.

|>  Am I also right at thinking that if I work with an object sbuf of a
|>  type derived from streambuf with the following construct:

|>  ostreambuf_iterator<char,char_traits<char> >  oi(&sbuf);

|>  , it guaranteed that the only possible exceprion is
|>  ios_base::failure? I think so because the Standard says
|>  basic_streambuf::overflow can report an error through throwing an
|>  exception.

See above.  An implementation might throw a double, or some special
class type, or anything else it felt like.  The only requirement is that
they document what they do.

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: kavdeiv@mail.ru (\" \")
Date: Thu, 8 Mar 2001 12:58:57 GMT
Raw View
Hi all,

Given an object sbuf of a type derived from streambuf, is it guaranteed that there is no possibility of me getting exceptions when reading the contents of the streambuf by means of the following construct:
istreambuf_iterator<char,char_traits<char> >  begin(&sbuf),  end;

I think that I'm guaranteed not to get any exceptions because istreambuf_iterators use members sbumpc and sgetc of the underlying stream buffer, which in turn may call underflow, and the Standard says that basic_streambuf::underflow can only report an error condition through returning traits::eof(). Am I right? Does it also mean that even if the streambuf object sbuf referrs to a filestream and the following is held:
has_facet<codecvt<char,char,char_traits<char>::state_type> >(sbuf.getloc()) == false
I still have underflow return traits::eof() without any possibility for bad_cast?

Am I also right at thinking that if I work with an object sbuf of a type derived from streambuf with the following construct:
ostreambuf_iterator<char,char_traits<char> >  oi(&sbuf);
, it guaranteed that the only possible exceprion is ios_bas::failure? I think so because the Standard says basic_streambuf::overflow can report an error through throwing an exception.

I'd be very appreciative to anybody who'll help me clarify that.

Kiril.


--
Posted from [212.64.94.65] by way of mx2.port.ru [194.67.23.33]
via Mailgate.ORG Server - http://www.Mailgate.ORG

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]
[ Note that the FAQ URL has changed!  Please update your bookmarks.     ]





Author: kavdeiv@mail.ru ("Kiril Avdeiv")
Date: Mon, 12 Mar 2001 22:18:03 GMT
Raw View
James, thank you very much for the exhaustive answer.

My subsequent studying of the relevant pages of the standard, I mean 17.4.8.8/3 that you pointed out to me, left me stunned. I find it very odd that such operations as sgetc, sbumpc, or underflow should be allowed to throw. I used to regard those member functions as a substitute for the C library functions getc, fgetc, ungetc. I could understand if the set of exceptions that might be thrown as a result of calling either sgetc or sbumpc was bounded - but allowing for throwing any exception is an overkill.

That means that such innocuously looking constructs as:

while(!traits::eq_int_type(ch = sbuf.sbumpc(), traits::eof()))  {
   // do something
}

or

istreambuf_iterator<char,char_traits<char> >  begin(&sbuf),  end;
while (begin != end) {
   // do something
}

may mysteriously fail due to an exception being thrown, and the worst thing is that one has absolutely no control over what sort of exception is thrown. One may argue that looking up those things in a particular implementation's documentation will dissolve the uncertainty. But what has that got to do with portability? I may wish to stick with another implementation of the Standard C++ library tomorrow, where the programmers had a different idea over what exceptions basic_streambuf::underflow can throw.

I, therefore, see only 2 ways of tackling the above nuisances:
1. Writing my own versions of streambuf iterators that would use the Standard C library calls getc, fgetc, ungetc (or, maybe, getwc, fgetwc, ungetwc) instead of the standard stream buffer's member functions. Or, rewriting by myself the standard buffer classes derived from basic_streambuf in such a way that the aforementioned member functions (plus a bunch of others, such as: sputn, sputc, sputn, overflow) do not throw (That will be also a standard conforming behaviour). That may require quite a bit of work, though.
2. Wait till the mess over exception related issues is cleared up in the Standard C++ I/O library. Please, don't think that I dislike the library itself, I do like it and find the ideas behind it innovative and clean. It's just that someone didn't realize all the implications of allowing for arbitrary types of exceptions for the operations that have long been regarded as not throwing.

Best wishes!

Kiril.

--
Posted from [213.17.96.79] by way of mx1.port.ru [194.67.23.32]
via Mailgate.ORG Server - http://www.Mailgate.ORG

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: James Kanze <kanze@gabi-soft.de>
Date: Tue, 13 Mar 2001 22:22:55 GMT
Raw View
kavdeiv@mail.ru ("Kiril Avdeiv") writes:

|>  James, thank you very much for the exhaustive answer.

|>  My subsequent studying of the relevant pages of the standard, I mean
|>  17.4.8.8/3 that you pointed out to me, left me stunned. I find it
|>  very odd that such operations as sgetc, sbumpc, or underflow should
|>  be allowed to throw. I used to regard those member functions as a
|>  substitute for the C library functions getc, fgetc, ungetc. I could
|>  understand if the set of exceptions that might be thrown as a result
|>  of calling either sgetc or sbumpc was bounded - but allowing for
|>  throwing any exception is an overkill.

I find it even odder that functions like std::max or std::min are
allowed to throw, and to throw anything.

|>  That means that such innocuously looking constructs as:

|>  while(!traits::eq_int_type(ch = sbuf.sbumpc(), traits::eof()))  {
|>     // do something
|>  }

|>  or

|>  istreambuf_iterator<char,char_traits<char> >  begin(&sbuf),  end;
|>  while (begin != end) {
|>     // do something
|>  }

|>  may mysteriously fail due to an exception being thrown, and the
|>  worst thing is that one has absolutely no control over what sort of
|>  exception is thrown. One may argue that looking up those things in a
|>  particular implementation's documentation will dissolve the
|>  uncertainty. But what has that got to do with portability? I may
|>  wish to stick with another implementation of the Standard C++
|>  library tomorrow, where the programmers had a different idea over
|>  what exceptions basic_streambuf::underflow can throw.

I sort of agree.  On the other hand, exceding the resource limits is
undefined behavior, and there are no minimum resource limits
guaranteed.  So the situation is even worse here; every possible program
potentially has undefined behavior.

In the end, you count on a (perhaps implicit) contract between you and
the implementor.  The standard is an important part of that contract,
but it isn't the whole contract.  It's fairly simple to create a
conforming implementation which is totally useless.  Implementors don't
do it, however.  In the case of resource limits, I don't see what the
alternatives are for the standard; there's not much an implementation
can do about it.  In the case of exceptions, I'm not particularly happy
about the situation, but I understand how it came about, I can (just
barely) live with it, counting on quality of implementation, and given
the historical context, I doubt that we could have expected more.

If you want more details, there was a long thread here recently on the
issue, mainly between myself and Dave Abraham.  You might try looking it
up on Google.

--
James Kanze                               mailto:kanze@gabi-soft.de
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]