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