locale::_Impl::_Impl and exceptions

Kevin Ediger kediger@licor.com
Mon Nov 15 10:35:00 GMT 1999


Hello,

The constructors for locale::__Impl
don't look correct to me. There are some try...catch handlers that
probably were intended to prevent memory leaks, but they don't do
that and I think a core dump is inevitable if an exception does
occur; the code deletes _M_facets and _M_category_names when the
compiler should have already taken care of that.

Here's a patch that uses auto_ptr to make the constructors exception
safe.

Best Regards,
Kevin Ediger


Index: src/locale.cc
===================================================================
RCS file: /cvs/libstdc++/libstdc++/src/locale.cc,v
retrieving revision 1.30
diff -u -p -r1.30 locale.cc
--- locale.cc	1999/08/26 08:51:15	1.30
+++ locale.cc	1999/11/15 18:19:51
@@ -36,6 +36,7 @@
 #include <bits/std_istream.h>
 #include <bits/std_ostream.h>
 #include <bits/std_vector.h>
+#include <bits/std_memory.h>      // for auto_ptr
 
 namespace std {
 
@@ -51,58 +52,46 @@ namespace std {
 
   locale::_Impl::_Impl(size_t __numfacets, size_t __refs)
   : _M_num_references(__refs - 1)
-    //  , _M_facets (numfacets, (facet*)0)
-    //  , _M_category_names (_S_num_categories, string ("*"))
+  , _M_facets (0)
+  , _M_category_names (0)
   , _M_has_name(false)
   , _M_cached_name_ok(false)
   , _M_cached_name(string ("*"))
   { 
     typedef vector<facet*, __STL_DEFAULT_ALLOCATOR(facet*) > __vec_facet;
     typedef vector<string, __STL_DEFAULT_ALLOCATOR(string) > __vec_string;
-    try {
-      _M_facets = new __vec_facet(__numfacets, (facet*)0);
-    }
-    catch (...) {
-      delete _M_facets;
-      throw;
-    }
-    try {
-       _M_category_names = new __vec_string(_S_num_categories, string("*"));
-    }
-    catch (...) {
-      delete _M_category_names;
-      throw;
-    }
+
+    auto_ptr<__vec_facet> __pvf(new __vec_facet(__numfacets,(facet*)0));
+    auto_ptr<__vec_string> __pcn(new __vec_string(_S_num_categories,string("*")));
+    _M_facets = __pvf.release();
+    _M_category_names = __pcn.release();
   }
   
   locale::_Impl::_Impl(const _Impl& __other, size_t __refs)
   : _M_num_references(__refs)
-    //  , _M_facets (other._M_facets)
-    //  , _M_category_names (other._M_category_names)
+  , _M_facets (0)
+  , _M_category_names (0)
   , _M_has_name(__other._M_has_name)
   , _M_cached_name_ok(__other._M_cached_name_ok)
   , _M_cached_name(__other._M_cached_name)
   {
     typedef vector<facet*, __STL_DEFAULT_ALLOCATOR(facet*) > __vec_facet;
     typedef vector<string, __STL_DEFAULT_ALLOCATOR(string) > __vec_string;
-    try {
-      _M_facets = new __vec_facet(*(__other._M_facets));
-    }
-    catch (...) {
-      delete _M_facets;
-      throw;
-    }
-    try {
-       _M_category_names = new __vec_string(*(__other._M_category_names));
-    }
-    catch (...) {
-      delete _M_category_names;
-      throw;
-    }
+
+    auto_ptr<__vec_facet> __pvf(new __vec_facet(*(__other._M_facets)));
+    auto_ptr<__vec_string> __pcn(new __vec_string(*(__other._M_category_names)));
 
-    std::vector<facet*>::iterator __it = _M_facets->begin();
-    for (; __it != _M_facets->end(); ++__it)
+    std::vector<facet*>::iterator __it = __pvf->begin();
+    for (; __it != __pvf->end(); ++__it)
       (*__it)->_M_add_reference();
+
+    /*
+     * these must be last since in the presence of an exception, the destructor 
+     * for this won't run until AFTER execution has passed  the closing brace
+     * of the constructor
+     */
+    _M_facets = __pvf.release();
+    _M_category_names = __pcn.release();
   }
   
   void
===================================================================

-- 
LI-COR, Inc.
Voice: 402.467.3576 ext 3695, Fax: 402.467.0872
mailto:kediger@licor.com
http://www.licor.com


More information about the Libstdc++ mailing list