libstdc++/10132: filebuf destructor throws exceptions
Benjamin Kosnik
bkoz@redhat.com
Thu Apr 24 06:06:00 GMT 2003
The following reply was made to PR libstdc++/10132; it has been noted by GNATS.
From: Benjamin Kosnik <bkoz@redhat.com>
To: =?ISO-8859-1?Q?P=E9tur_Run=F3lfsson?= <peturr02@ru.is>
Cc: gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Subject: Re: libstdc++/10132: filebuf destructor throws exceptions
Date: Thu, 24 Apr 2003 01:05:21 -0500
Here's something to think about. I think this is pretty good. Something
like it will have to be done for the corresponding underflow bits.
-benjamin
2003-04-24 Benjamin Kosnik <bkoz@redhat.com>
PR libstdc++/10132
* include/std/std_fstream.h (basic_filebuf): Remove __res_type
typedef.
* src/fstream.cc: Same.
* include/bits/fstream.tcc
(basic_filebuf::_M_convert_to_external): Simplify. Add try/catch
blocks.
Index: include/bits/fstream.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/fstream.tcc,v
retrieving revision 1.65
diff -c -p -r1.65 fstream.tcc
*** include/bits/fstream.tcc 22 Apr 2003 17:32:25 -0000 1.65
--- include/bits/fstream.tcc 24 Apr 2003 05:59:23 -0000
*************** namespace std
*** 283,353 ****
_M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
streamsize& __elen, streamsize& __plen)
{
! const locale __loc = this->getloc();
! const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
! // Sync with stdio.
! const bool __sync = this->_M_buf_size <= 1;
!
! if (__cvt.always_noconv() && __ilen)
! {
! __elen +=
! _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen, __sync);
! __plen += __ilen;
! }
! else
{
! // Worst-case number of external bytes needed.
! int __ext_multiplier = __cvt.encoding();
! if (__ext_multiplier == -1 || __ext_multiplier == 0)
! __ext_multiplier = sizeof(char_type);
! streamsize __blen = __ilen * __ext_multiplier;
! char* __buf = static_cast<char*>(__builtin_alloca(__blen));
! char* __bend;
! const char_type* __iend;
! __res_type __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen,
! __iend, __buf, __buf + __blen, __bend);
!
! if (__r == codecvt_base::ok || __r == codecvt_base::partial)
! __blen = __bend - __buf;
! // Similarly to the always_noconv case above.
! else if (__r == codecvt_base::noconv)
! {
! __buf = reinterpret_cast<char*>(__ibuf);
! __blen = __ilen;
! }
! // Result == error
! else
! __blen = 0;
!
! if (__blen)
{
! __elen += _M_file.xsputn(__buf, __blen, __sync);
! __plen += __blen;
}
!
! // Try once more for partial conversions.
! if (__r == codecvt_base::partial)
{
! const char_type* __iresume = __iend;
! streamsize __rlen = this->_M_out_lim - __iend;
! __r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen,
__iend, __buf, __buf + __blen, __bend);
! if (__r != codecvt_base::error)
! __rlen = __bend - __buf;
else
{
! __rlen = 0;
! // Signal to the caller (_M_really_overflow) that
! // codecvt::out eventually failed.
! __elen = 0;
}
! if (__rlen)
{
! __elen += _M_file.xsputn(__buf, __rlen, __sync);
! __plen += __rlen;
}
}
}
}
template<typename _CharT, typename _Traits>
--- 283,357 ----
_M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
streamsize& __elen, streamsize& __plen)
{
! try
{
! // Sync with stdio.
! const bool __sync = this->_M_buf_size <= 1;
! const locale __loc = this->getloc();
! const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
!
! if (__cvt.always_noconv() && __ilen)
{
! __elen += _M_file.xsputn(reinterpret_cast<char*>(__ibuf),
! __ilen, __sync);
! __plen += __ilen;
}
! else
{
! // Worst-case number of external bytes needed.
! int __ext_multiplier = __cvt.encoding();
! if (__ext_multiplier == -1 || __ext_multiplier == 0)
! __ext_multiplier = sizeof(char_type);
! streamsize __blen = __ilen * __ext_multiplier;
! char* __buf = static_cast<char*>(__builtin_alloca(__blen));
! char* __bend;
! const char_type* __iend;
! codecvt_base::result __r;
! __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen,
__iend, __buf, __buf + __blen, __bend);
!
! if (__r == codecvt_base::ok || __r == codecvt_base::partial)
! __blen = __bend - __buf;
! else if (__r == codecvt_base::noconv)
! {
! // Same as the always_noconv case above.
! __buf = reinterpret_cast<char*>(__ibuf);
! __blen = __ilen;
! }
else
{
! // Result == error
! __blen = 0;
}
!
! if (__blen)
{
! __elen += _M_file.xsputn(__buf, __blen, __sync);
! __plen += __blen;
! }
!
! // Try once more for partial conversions.
! if (__r == codecvt_base::partial)
! {
! const char_type* __iresume = __iend;
! streamsize __rlen = this->_M_out_lim - __iend;
! __r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen,
! __iend, __buf, __buf + __blen, __bend);
! if (__r != codecvt_base::error)
! {
! __rlen = __bend - __buf;
! __elen += _M_file.xsputn(__buf, __rlen, __sync);
! __plen += __rlen;
! }
}
}
}
+ catch(...)
+ {
+ // Something went wrong with the conversion.
+ if (__elen && __elen == __plen)
+ __throw_exception_again;
+ }
}
template<typename _CharT, typename _Traits>
*************** namespace std
*** 394,400 ****
char_type __pending = traits_type::to_char_type(__c);
_M_convert_to_external(&__pending, 1, __elen, __plen);
! // User code must flush when switching modes (thus don't sync).
if (__elen == __plen && __elen)
{
_M_set_indeterminate();
--- 398,405 ----
char_type __pending = traits_type::to_char_type(__c);
_M_convert_to_external(&__pending, 1, __elen, __plen);
! // User code must flush when switching modes (thus
! // don't sync).
if (__elen == __plen && __elen)
{
_M_set_indeterminate();
Index: include/std/std_fstream.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/std/std_fstream.h,v
retrieving revision 1.29
diff -c -p -r1.29 std_fstream.h
*** include/std/std_fstream.h 22 Apr 2003 17:32:25 -0000 1.29
--- include/std/std_fstream.h 24 Apr 2003 05:59:24 -0000
*************** namespace std
*** 81,87 ****
typedef __basic_file<char> __file_type;
typedef typename traits_type::state_type __state_type;
typedef codecvt<char_type, char, __state_type> __codecvt_type;
- typedef typename __codecvt_type::result __res_type;
typedef ctype<char_type> __ctype_type;
//@}
--- 81,86 ----
Index: src/fstream.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/fstream.cc,v
retrieving revision 1.8
diff -c -p -r1.8 fstream.cc
*** src/fstream.cc 20 Apr 2003 13:54:45 -0000 1.8
--- src/fstream.cc 24 Apr 2003 05:59:25 -0000
*************** namespace std
*** 177,192 ****
const char* __eend;
char_type* __iend;
! __res_type __r = __cvt.in(_M_state_cur, __buf,
! __buf + __elen, __eend, _M_in_beg,
! _M_in_beg + _M_buf_size, __iend);
if (__r == codecvt_base::ok)
__ilen = __iend - _M_in_beg;
else
{
// Unwind.
__ilen = 0;
! _M_file.seekoff(-__elen, ios_base::cur, __sync, ios_base::in);
}
}
--- 177,194 ----
const char* __eend;
char_type* __iend;
! codecvt_base::result __r;
! __r = __cvt.in(_M_state_cur,
! __buf, __buf + __elen, __eend,
! _M_in_beg, _M_in_beg + _M_buf_size, __iend);
if (__r == codecvt_base::ok)
__ilen = __iend - _M_in_beg;
else
{
// Unwind.
__ilen = 0;
! _M_file.seekoff(-__elen, ios_base::cur, __sync,
! ios_base::in);
}
}
More information about the Gcc-prs
mailing list