[PATCH] Fix memory leak in std::moneypunct

Andreas Schwab schwab@suse.de
Mon Jan 26 16:14:00 GMT 2004


Paolo Carlini <pcarlini@suse.de> writes:

> The patch is ok for 3.4 and 3.5 of course and the try/catch block itself
> should be added to 3.3 too since we have already patched all the other
> possible causes of memory leaks there too... Are you willing to do that?

How about this?  Regtested on ia64-linux.

2004-01-26  Andreas Schwab  <schwab@suse.de>

	* config/locale/gnu/monetary_members.cc
	(moneypunct<wchar_t, true/false>::_M_initialize_moneypunct): Don't
	leak memory if new throws.

--- libstdc++-v3/config/locale/gnu/monetary_members.cc.~1.7.2.1.~	2003-02-28 10:13:32.000000000 +0100
+++ libstdc++-v3/config/locale/gnu/monetary_members.cc	2004-01-26 00:49:05.000000000 +0100
@@ -1,6 +1,6 @@
 // std::moneypunct implementation details, GNU version -*- C++ -*-
 
-// Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -356,46 +356,63 @@ namespace std
 	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
 	  const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc);
 
-	  mbstate_t __state;
-	  size_t __len = strlen(__cpossign);
-	  if (__len)
-	    {
-	      ++__len;
-	      memset(&__state, 0, sizeof(mbstate_t));
-	      wchar_t* __wcs = new wchar_t[__len];
-	      mbsrtowcs(__wcs, &__cpossign, __len, &__state);
-	      _M_positive_sign = __wcs;
-	    }
-	  else
-	    _M_positive_sign = L"";
-
+	  wchar_t* __wcs_ps = 0;
+	  wchar_t* __wcs_ns = 0;
 	  char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
-	  __len = strlen(__cnegsign);
-	  if (!__nposn)
-	    _M_negative_sign = L"()";
-	  else if (__len)
-	    { 
-	      ++__len;
-	      memset(&__state, 0, sizeof(mbstate_t));
-	      wchar_t* __wcs = new wchar_t[__len];
-	      mbsrtowcs(__wcs, &__cnegsign, __len, &__state);
-	      _M_negative_sign = __wcs;
-	    }
-	  else
-	    _M_negative_sign = L"";
-
-	  // _Intl == true.
-	  __len = strlen(__ccurr);
-	  if (__len)
+	  try
 	    {
-	      ++__len;
-	      memset(&__state, 0, sizeof(mbstate_t));
-	      wchar_t* __wcs = new wchar_t[__len];
-	      mbsrtowcs(__wcs, &__ccurr, __len, &__state);
-	      _M_curr_symbol = __wcs;
+	      mbstate_t __state;
+	      size_t __len = strlen(__cpossign);
+	      if (__len)
+		{
+		  ++__len;
+		  memset(&__state, 0, sizeof(mbstate_t));
+		  __wcs_ps = new wchar_t[__len];
+		  mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
+		  _M_positive_sign = __wcs_ps;
+		}
+	      else
+		_M_positive_sign = L"";
+
+	      __len = strlen(__cnegsign);
+	      if (!__nposn)
+		_M_negative_sign = L"()";
+	      else if (__len)
+		{
+		  ++__len;
+		  memset(&__state, 0, sizeof(mbstate_t));
+		  __wcs_ns = new wchar_t[__len];
+		  mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
+		  _M_negative_sign = __wcs_ns;
+		}
+	      else
+		_M_negative_sign = L"";
+
+	      // _Intl == true.
+	      __len = strlen(__ccurr);
+	      if (__len)
+		{
+		  ++__len;
+		  memset(&__state, 0, sizeof(mbstate_t));
+		  wchar_t* __wcs = new wchar_t[__len];
+		  mbsrtowcs(__wcs, &__ccurr, __len, &__state);
+		  _M_curr_symbol = __wcs;
+		}
+	      else
+		_M_curr_symbol = L"";
 	    }
-	  else
-	    _M_curr_symbol = L"";
+	  catch (...)
+	    {
+	      delete __wcs_ps;
+	      delete __wcs_ns;
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+	      __uselocale(__old);
+#else
+	      setlocale(LC_ALL, __old);
+	      free(__old);
+#endif
+	      __throw_exception_again;
+	    } 
 
 	  _M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc));
 	  char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
@@ -456,47 +473,64 @@ namespace std
 	  const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc);
 	  const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc);
 
-	  mbstate_t __state;
-	  size_t __len;
-	  __len = strlen(__cpossign);
-	  if (__len)
-	    {
-	      ++__len;
-	      memset(&__state, 0, sizeof(mbstate_t));
-	      wchar_t* __wcs = new wchar_t[__len];
-	      mbsrtowcs(__wcs, &__cpossign, __len, &__state);
-	      _M_positive_sign = __wcs;
-	    }
-	  else
-	    _M_positive_sign = L"";
-
+	  wchar_t* __wcs_ps = 0;
+	  wchar_t* __wcs_ns = 0;
 	  char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
-	  __len = strlen(__cnegsign);
-	  if (!__nposn)
-	    _M_negative_sign = L"()";
-	  else if (__len)
-	    { 
-	      ++__len;
-	      memset(&__state, 0, sizeof(mbstate_t));
-	      wchar_t* __wcs = new wchar_t[__len];
-	      mbsrtowcs(__wcs, &__cnegsign, __len, &__state);
-	      _M_negative_sign = __wcs;
-	    }
-	  else
-	    _M_negative_sign = L"";
-
-	  // _Intl == true.
-	  __len = strlen(__ccurr);
-	  if (__len)
+	  try
 	    {
-	      ++__len;
-	      memset(&__state, 0, sizeof(mbstate_t));
-	      wchar_t* __wcs = new wchar_t[__len];
-	      mbsrtowcs(__wcs, &__ccurr, __len, &__state);
-	      _M_curr_symbol = __wcs;
+	      mbstate_t __state;
+	      size_t __len;
+	      __len = strlen(__cpossign);
+	      if (__len)
+		{
+		  ++__len;
+		  memset(&__state, 0, sizeof(mbstate_t));
+		  __wcs_ps = new wchar_t[__len];
+		  mbsrtowcs(__wcs_ps, &__cpossign, __len, &__state);
+		  _M_positive_sign = __wcs_ps;
+		}
+	      else
+		_M_positive_sign = L"";
+
+	      __len = strlen(__cnegsign);
+	      if (!__nposn)
+		_M_negative_sign = L"()";
+	      else if (__len)
+		{
+		  ++__len;
+		  memset(&__state, 0, sizeof(mbstate_t));
+		  __wcs_ns = new wchar_t[__len];
+		  mbsrtowcs(__wcs_ns, &__cnegsign, __len, &__state);
+		  _M_negative_sign = __wcs_ns;
+		}
+	      else
+		_M_negative_sign = L"";
+
+	      // _Intl == true.
+	      __len = strlen(__ccurr);
+	      if (__len)
+		{
+		  ++__len;
+		  memset(&__state, 0, sizeof(mbstate_t));
+		  wchar_t* __wcs = new wchar_t[__len];
+		  mbsrtowcs(__wcs, &__ccurr, __len, &__state);
+		  _M_curr_symbol = __wcs;
+		}
+	      else
+		_M_curr_symbol = L"";
 	    }
-	  else
-	    _M_curr_symbol = L"";
+	  catch (...)
+	    {
+	      delete __wcs_ps;
+	      delete __wcs_ns;
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+	      __uselocale(__old);
+#else
+	      setlocale(LC_ALL, __old);
+	      free(__old);
+#endif
+	      __throw_exception_again;
+	    } 
 
 	  _M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
 	  char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."



More information about the Libstdc++ mailing list