This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [Patch] Fix libstdc++/12540
- From: Paolo Carlini <pcarlini at unitus dot it>
- To: Paolo Carlini <pcarlini at unitus dot it>
- Cc: libstdc++ at gcc dot gnu dot org
- Date: Thu, 16 Oct 2003 18:42:04 +0200
- Subject: Re: [Patch] Fix libstdc++/12540
- References: <3F8E496C.2020207@unitus.it> <3F8E57BB.3030404@unitus.it>
Hi again,
further testing (LC_ALL unset, LANG = xxx (!= "C"), at least one
category set to != xxx) revealed another possible memory leak path,
which may occur if memory allocation inside __str throws.
Therefore, instead of dealing explicitly, with this case too, seems
much better to me to change my original code for locale(const char*)
to not use strdup at all, but instead another basic_string for
__res too.
I have therefore tested the below, which I will commit soon.
Now, *always* for 12352 :)
==3673== LEAK SUMMARY:
==3673== definitely lost: 0 bytes in 0 blocks.
==3673== possibly lost: 0 bytes in 0 blocks.
==3673== still reachable: 17840 bytes in 6 blocks.
==3673== suppressed: 0 bytes in 0 blocks.
Paolo.
//////////
2003-10-16 Paolo Carlini <pcarlini@suse.de>
PR libstdc++/12540
* config/locale/gnu/monetary_members.cc
(moneypunct<wchar_t, true/false>::_M_initialize_moneypunct):
Don't leak memory if new throws.
* src/locale.cc (locale::locale(const char*)): In order not
to leak memory in case new throws, use a basic_string type
for __res too and avoid strdup.
diff -urN libstdc++-v3-orig/config/locale/gnu/monetary_members.cc libstdc++-v3/config/locale/gnu/monetary_members.cc
--- libstdc++-v3-orig/config/locale/gnu/monetary_members.cc 2003-07-18 04:27:15.000000000 +0200
+++ libstdc++-v3/config/locale/gnu/monetary_members.cc 2003-10-16 09:29:13.000000000 +0200
@@ -379,47 +379,60 @@
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)
+ wchar_t* __wcs_ps = 0;
+ wchar_t* __wcs_ns = 0;
+ const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
+ try
{
- ++__len;
- memset(&__state, 0, sizeof(mbstate_t));
- wchar_t* __wcs = new wchar_t[__len];
- mbsrtowcs(__wcs, &__cpossign, __len, &__state);
- _M_data->_M_positive_sign = __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_data->_M_positive_sign = __wcs_ps;
+ }
+ else
+ _M_data->_M_positive_sign = L"";
+
+ __len = strlen(__cnegsign);
+ if (!__nposn)
+ _M_data->_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_data->_M_negative_sign = __wcs_ns;
+ }
+ else
+ _M_data->_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_data->_M_curr_symbol = __wcs;
+ }
+ else
+ _M_data->_M_curr_symbol = L"";
}
- else
- _M_data->_M_positive_sign = L"";
-
- char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc));
- __len = strlen(__cnegsign);
- if (!__nposn)
- _M_data->_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_data->_M_negative_sign = __wcs;
- }
- else
- _M_data->_M_negative_sign = L"";
-
- // _Intl == true.
- __len = strlen(__ccurr);
- if (__len)
+ catch (...)
{
- ++__len;
- memset(&__state, 0, sizeof(mbstate_t));
- wchar_t* __wcs = new wchar_t[__len];
- mbsrtowcs(__wcs, &__ccurr, __len, &__state);
- _M_data->_M_curr_symbol = __wcs;
- }
- else
- _M_data->_M_curr_symbol = L"";
-
+ delete _M_data;
+ _M_data = 0;
+ delete __wcs_ps;
+ delete __wcs_ns;
+ __throw_exception_again;
+ }
+
_M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS,
__cloc));
char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc));
@@ -442,18 +455,18 @@
}
template<>
- void
- moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
-#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
- const char*)
+ void
+ moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc,
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
+ const char*)
#else
- const char* __name)
+ const char* __name)
#endif
- {
- if (!_M_data)
- _M_data = new __moneypunct_cache<wchar_t>;
+ {
+ if (!_M_data)
+ _M_data = new __moneypunct_cache<wchar_t>;
- if (!__cloc)
+ if (!__cloc)
{
// "C" locale
_M_data->_M_decimal_point = L'.';
@@ -489,47 +502,60 @@
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_data->_M_positive_sign = __wcs;
+ wchar_t* __wcs_ps = 0;
+ wchar_t* __wcs_ns = 0;
+ const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
+ try
+ {
+ 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_data->_M_positive_sign = __wcs_ps;
+ }
+ else
+ _M_data->_M_positive_sign = L"";
+
+ __len = strlen(__cnegsign);
+ if (!__nposn)
+ _M_data->_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_data->_M_negative_sign = __wcs_ns;
+ }
+ else
+ _M_data->_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_data->_M_curr_symbol = __wcs;
+ }
+ else
+ _M_data->_M_curr_symbol = L"";
}
- else
- _M_data->_M_positive_sign = L"";
-
- char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc));
- __len = strlen(__cnegsign);
- if (!__nposn)
- _M_data->_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_data->_M_negative_sign = __wcs;
- }
- else
- _M_data->_M_negative_sign = L"";
-
- // _Intl == true.
- __len = strlen(__ccurr);
- if (__len)
+ catch (...)
{
- ++__len;
- memset(&__state, 0, sizeof(mbstate_t));
- wchar_t* __wcs = new wchar_t[__len];
- mbsrtowcs(__wcs, &__ccurr, __len, &__state);
- _M_data->_M_curr_symbol = __wcs;
+ delete _M_data;
+ _M_data = 0;
+ delete __wcs_ps;
+ delete __wcs_ns;
+ __throw_exception_again;
}
- else
- _M_data->_M_curr_symbol = L"";
_M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc));
char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc));
diff -urN libstdc++-v3-orig/src/locale.cc libstdc++-v3/src/locale.cc
--- libstdc++-v3-orig/src/locale.cc 2003-10-14 12:37:36.000000000 +0200
+++ libstdc++-v3/src/locale.cc 2003-10-16 18:21:49.000000000 +0200
@@ -208,20 +208,20 @@
}
else
{
- char* __res;
+ string __res;
// LANG may set a default different from "C".
char* __env = std::getenv("LANG");
if (!__env || std::strcmp(__env, "") == 0
|| std::strcmp(__env, "C") == 0
|| std::strcmp(__env, "POSIX") == 0)
- __res = strdup("C");
+ __res = "C";
else
- __res = strdup(__env);
+ __res = __env;
// Scan the categories looking for the first one
// different from LANG.
size_t __i = 0;
- if (std::strcmp(__res, "C") == 0)
+ if (std::strcmp(__res.c_str(), "C") == 0)
for (; __i < _S_categories_size; ++__i)
{
__env = std::getenv(_S_categories[__i]);
@@ -235,7 +235,7 @@
{
__env = std::getenv(_S_categories[__i]);
if (__env && std::strcmp(__env, "") != 0
- && std::strcmp(__env, __res) != 0)
+ && std::strcmp(__env, __res.c_str()) != 0)
break;
}
@@ -285,11 +285,10 @@
}
// ... otherwise either an additional instance of
// the "C" locale or LANG.
- else if (std::strcmp(__res, "C") == 0)
+ else if (std::strcmp(__res.c_str(), "C") == 0)
(_M_impl = _S_classic)->_M_add_reference();
else
- _M_impl = new _Impl(__res, 1);
- std::free(__res);
+ _M_impl = new _Impl(__res.c_str(), 1);
}
}
}