[PATCH] Slightly better way to __USE_MALLOC

Brad Spencer spencer@infointeractive.com
Thu Oct 10 16:59:00 GMT 2002


On Thu, Oct 10, 2002 at 05:46:08PM -0500, Loren James Rittle wrote:
> OK, you said that you had an example, but this is exactly what we want
> to avoid (by catching at compile-time):

Yes.  Using your example specifically, here's what I have working
currently in my testbed.  Please excuse the long paths.

eng-linux1:/build/eng-linux1/spencer/gcc-cross/test/loren$ cat a.cc
//a.C
#include <list>

void foo (std::list<int>& a)
{
  a.pop_back ();
}

eng-linux1:/build/eng-linux1/spencer/gcc-cross/test/loren$ cat b.cc
//b.C
#include <list>

void foo (std::list<int>& a);

int main (void)
{
  std::list<int> a;

  a.push_back (1);

  foo (a);
}

The library is built with the default pool allocator:

$ nm --defined-only
/build/eng-linux1/spencer/test-gcc/i686-pc-linux-gnu/lib/libstdc++.a
|grep __node_allocator_is
/build/eng-linux1/spencer/test-gcc/i686-pc-linux-gnu/lib/libstdc++.a:stl-inst.o:00000000
R std::__node_allocator_is_default_alloc_template

Link error when either object doesn't define the macro properly (look
for the "__node_allocator_is" lines):

eng-linux1:/build/eng-linux1/spencer/gcc-cross/test/loren$
CXX=/build/eng-linux1/spencer/test-gcc/i686-pc-linux-gnu/bin/g++ make
clean all BREAK_IT=1 FILE_TO_BREAK=a
rm -f a.o b.o loren
/build/eng-linux1/spencer/test-gcc/i686-pc-linux-gnu/bin/g++ -Wall -O2
-D_GLIBCPP_USE_MALLOC=1 -c -o a.o a.cc
/build/eng-linux1/spencer/test-gcc/i686-pc-linux-gnu/bin/g++ -Wall -O2
-c -o b.o b.cc
/build/eng-linux1/spencer/test-gcc/i686-pc-linux-gnu/bin/g++ -Wall -O2
-o loren a.o b.o
a.o(.data+0x0): undefined reference to
`std::__node_allocator_is_malloc_alloc_template'
collect2: ld returned 1 exit status
make: *** [loren] Error 1

eng-linux1:/build/eng-linux1/spencer/gcc-cross/test/loren$
CXX=/build/eng-linux1/spencer/test-gcc/i686-pc-linux-gnu/bin/g++ make
clean all BREAK_IT=1 FILE_TO_BREAK=b
rm -f a.o b.o loren
/build/eng-linux1/spencer/test-gcc/i686-pc-linux-gnu/bin/g++ -Wall -O2
  -c -o a.o a.cc
/build/eng-linux1/spencer/test-gcc/i686-pc-linux-gnu/bin/g++ -Wall -O2
-D_GLIBCPP_USE_MALLOC=1 -c -o b.o b.cc
/build/eng-linux1/spencer/test-gcc/i686-pc-linux-gnu/bin/g++ -Wall -O2
-o loren a.o b.o
b.o: In function `main':
b.o(.text+0x88): undefined reference to
`std::__malloc_alloc_template<(int)0>::_S_oom_malloc(unsigned)'
b.o(.data+0x0): undefined reference to
`std::__node_allocator_is_malloc_alloc_template'
b.o: In function `std::list<int, std::allocator<int>
>::insert(std::_List_iterator<int, int&, int*>, int const&)':
b.o(.gnu.linkonce.t._ZNSt4listIiSaIiEE6insertESt14_List_iteratorIiRiPiERKi+0x61):
undefined reference to
`std::__malloc_alloc_template<(int)0>::_S_oom_malloc(unsigned)'
collect2: ld returned 1 exit status
make: *** [loren] Error 1

And likewise when the library is build to use malloc (although
c++config defines the macro and you have to go out of your way to make
it not do that.  I'm simulating the condition where the headers are
installed once, but a malloc-using library is being pulled in, like I
described in my original message).  Only objects that also used malloc
will link.   

I've attached the diff in its current state for reference.  I'm now
basing this off the trunk CVS version instead of gcc-3.2.

-- 
------------------------------------------------------------------
Brad Spencer - spencer@infointeractive.com - "It's quite nice..."
Systems Architect | InfoInterActive Corp. | A Canadian AOL Company
-------------- next part --------------
Index: acconfig.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/acconfig.h,v
retrieving revision 1.25
diff -u -p -r1.25 acconfig.h
--- acconfig.h	14 Dec 2001 21:06:32 -0000	1.25
+++ acconfig.h	10 Oct 2002 23:57:39 -0000
@@ -37,6 +37,9 @@
 // Define to use concept checking code from the boost libraries.
 #undef _GLIBCPP_CONCEPT_CHECKS
 
+// Define to use the malloc-based allocator instead pool-based one
+#undef _GLIBCPP_USE_MALLOC
+
 // Define if you have the atan2f function.
 #undef _GLIBCPP_HAVE_ATAN2F 
 
Index: acinclude.m4
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/acinclude.m4,v
retrieving revision 1.220
diff -u -p -r1.220 acinclude.m4
--- acinclude.m4	17 Sep 2002 05:50:31 -0000	1.220
+++ acinclude.m4	10 Oct 2002 23:57:40 -0000
@@ -2106,6 +2106,38 @@ fi
 
 
 dnl
+dnl Check for whether the _GLIBCPP_USE_MALLOC macro should be defined and thus
+dnl whether the library should be built with the malloc-based allocator
+dnl underneath the STL containers instead of the pool-based allocator.
+dnl
+dnl GLIBCPP_ENABLE_POOL_ALLOCATOR
+dnl --enable-pool-allocator enables the pool-based allocator.
+dnl --disable-pool-allocator turns it off off.
+dnl  +  Usage:  GLIBCPP_ENABLE_USE_MALLOC[(DEFAULT)]
+dnl       Where DEFAULT is either `yes' or `no'.  If ommitted, it
+dnl       defaults to `yes'.
+AC_DEFUN(GLIBCPP_ENABLE_POOL_ALLOCATOR, [dnl
+define([GLIBCPP_ENABLE_POOL_ALLOCATOR_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(pool-allocator,
+changequote(<<, >>)dnl
+<<  --enable-pool-allocator use the fast pool-based allocator [default=>>GLIBCPP_ENABLE_POOL_ALLOCATOR_DEFAULT],
+changequote([, ])dnl
+[case "$enableval" in
+ yes) enable_pool_allocator=yes ;;
+ no)  enable_pool_allocator=no ;;
+ *)   AC_MSG_ERROR([Unknown argument to enable/disable pool allocator]) ;;
+ esac],
+enable_pool_allocator=GLIBCPP_ENABLE_POOL_ALLOCATOR_DEFAULT)dnl
+dnl Option parsed, now set things appropriately
+AC_MSG_CHECKING([whether to use pool allocator])
+if test x"$enable_pool_allocator" = xno; then
+  AC_DEFINE(_GLIBCPP_USE_MALLOC)
+fi
+AC_MSG_RESULT($enable_pool_allocator)
+])
+
+
+dnl
 dnl Add version tags to symbols in shared library (or not), additionally
 dnl marking other symbols as private/local (or not).
 dnl
Index: config.h.in
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/config.h.in,v
retrieving revision 1.56
diff -u -p -r1.56 config.h.in
--- config.h.in	11 Jun 2002 17:53:59 -0000	1.56
+++ config.h.in	10 Oct 2002 23:57:40 -0000
@@ -24,6 +24,9 @@
 // Define to use concept checking code from the boost libraries.
 #undef _GLIBCPP_CONCEPT_CHECKS
 
+// Define to use the malloc-based allocator instead pool-based one
+#undef _GLIBCPP_USE_MALLOC
+
 // Define if mbstate_t exists in wchar.h.
 #undef HAVE_MBSTATE_T
 
Index: configure.in
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/configure.in,v
retrieving revision 1.105
diff -u -p -r1.105 configure.in
--- configure.in	26 Sep 2002 05:25:05 -0000	1.105
+++ configure.in	10 Oct 2002 23:57:40 -0000
@@ -66,6 +66,7 @@ GLIBCPP_ENABLE_CXX_FLAGS([none])
 GLIBCPP_ENABLE_SJLJ_EXCEPTIONS
 GLIBCPP_ENABLE_LIBUNWIND_EXCEPTIONS
 GLIBCPP_ENABLE_CONCEPT_CHECKS
+GLIBCPP_ENABLE_POOL_ALLOCATOR        
 
 # Check for headers necessary for libsupc++ using dyn-string.c/cxa_demangle.c
 AC_CHECK_HEADERS(string.h stdlib.h)
Index: include//backward/alloc.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/backward/alloc.h,v
retrieving revision 1.11
diff -u -p -r1.11 alloc.h
--- include//backward/alloc.h	6 Dec 2001 20:29:30 -0000	1.11
+++ include//backward/alloc.h	10 Oct 2002 23:57:40 -0000
@@ -53,10 +53,10 @@ using std::__debug_alloc; 
 using std::__alloc; 
 using std::__single_client_alloc; 
 using std::allocator;
-#ifdef __USE_MALLOC
-using std::malloc_alloc; 
-#else
-using std::__default_alloc_template; 
-#endif
+#ifdef _GLIBCPP_USE_MALLOC
+using std::__malloc_alloc_template;
+#else /* _GLIBCPP_USE_MALLOC */
+using std::__default_alloc_template;
+#endif /* _GLIBCPP_USE_MALLOC */
 
 #endif 
Index: include//bits/c++config
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/c++config,v
retrieving revision 1.505
diff -u -p -r1.505 c++config
--- include//bits/c++config	7 Oct 2002 07:19:04 -0000	1.505
+++ include//bits/c++config	10 Oct 2002 23:57:40 -0000
@@ -69,15 +69,19 @@
 // that threads are properly configured on your platform before
 // assigning blame to the STL container-memory allocator.  After doing
 // so, please report any possible issues to libstdc++@gcc.gnu.org .
-// Do not define __USE_MALLOC on the command line.  Enforce it here:
-#ifdef __USE_MALLOC
-#error __USE_MALLOC should only be defined within \
-libstdc++-v3/include/bits/c++config before full recompilation of the library.
-#endif
-// Define __USE_MALLOC after this point in the file in order to aid debugging
-// or globally change allocation policy.  This breaks the ABI, thus
-// completely recompile the library.  A patch to better support
-// changing the global allocator policy would be probably be accepted.
+//
+// TODO: XXX Fix this comment!
+// Do not arbitrarily define _GLIBCPP_USE_MALLOC on the command line.
+// It must be defined at library-build time (via the
+// --enable-pool-allocator option).  Configure the library to use
+// malloc (via --enable-pool-allocator=no) in order to aid debugging or
+// globally change allocation policy.  This breaks the ABI, thus
+// completely recompile the library.
+//
+// See libstdc++-v3/docs/html/configopts.html for details.
+//
+// A patch to better support changing the global allocator policy would be
+// probably be accepted. 
 
 // The remainder of the prewritten config is mostly automatic; all the
 // user hooks are listed above.
Index: include//bits/stl_alloc.h
===================================================================
RCS file: /cvsroot/gcc/gcc/libstdc++-v3/include/bits/stl_alloc.h,v
retrieving revision 1.24
diff -u -p -r1.24 stl_alloc.h
--- include//bits/stl_alloc.h	23 Aug 2002 16:52:29 -0000	1.24
+++ include//bits/stl_alloc.h	10 Oct 2002 23:57:41 -0000
@@ -212,7 +212,7 @@ namespace std
 
 
   // Determines the underlying allocator choice for the node allocator.
-#ifdef __USE_MALLOC
+#ifdef _GLIBCPP_USE_MALLOC
   typedef __malloc_alloc_template<0>  __mem_interface;
 #else
   typedef __new_alloc                 __mem_interface;
@@ -306,14 +306,13 @@ namespace std
 #endif
     };
 
-
-#ifdef __USE_MALLOC
-
+#ifdef _GLIBCPP_USE_MALLOC
+  
+  // Use the malloc-based allocator for all node allocations themselves
   typedef __mem_interface __alloc;
   typedef __mem_interface __single_client_alloc;
-
-#else
-
+  
+#else /* _GLIBCPP_USE_MALLOC */
 
   /**
    *  @if maint
@@ -616,9 +615,11 @@ namespace std
     typename __default_alloc_template<__threads,__inst>::_Obj* volatile
     __default_alloc_template<__threads,__inst>::_S_free_list[_NFREELISTS];
 
+  // Use the pool-based allocator for all node allocations themselves
   typedef __default_alloc_template<true,0>    __alloc;
   typedef __default_alloc_template<false,0>   __single_client_alloc;
-#endif /* ! __USE_MALLOC */
+  
+#endif /* ! _GLIBCPP_USE_MALLOC */
 
 
   /**
@@ -628,7 +629,7 @@ namespace std
    *  of stl_alloc.h.)
    *
    *  The underlying allocator behaves as follows.
-   *  - if __USE_MALLOC then
+   *  - if _GLIBCPP_USE_MALLOC then
    *    - thread safety depends on malloc and is entirely out of our hands
    *    - __malloc_alloc_template is used for memory requests
    *  - else (the default)
@@ -908,7 +909,7 @@ namespace std
       typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
     };
 
-#ifndef __USE_MALLOC
+#ifndef _GLIBCPP_USE_MALLOC
   template<typename _Tp, bool __threads, int __inst>
     struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> >
     {
@@ -918,7 +919,7 @@ namespace std
       typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> >
       allocator_type;
     };
-#endif
+#endif /* _GLIBCPP_USE_MALLOC */
 
   template<typename _Tp, typename _Alloc>
     struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> >
@@ -941,7 +942,7 @@ namespace std
       typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
     };
 
-#ifndef __USE_MALLOC
+#ifndef _GLIBCPP_USE_MALLOC
   template<typename _Tp, typename _Tp1, bool __thr, int __inst>
     struct _Alloc_traits<_Tp, __allocator<_Tp1, __default_alloc_template<__thr, __inst> > >
     {
@@ -951,7 +952,7 @@ namespace std
       typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> >
       allocator_type;
     };
-#endif
+#endif /* _GLIBCPP_USE_MALLOC */
 
   template<typename _Tp, typename _Tp1, typename _Alloc>
     struct _Alloc_traits<_Tp, __allocator<_Tp1, __debug_alloc<_Alloc> > >
@@ -967,9 +968,14 @@ namespace std
   // NB: This syntax is a GNU extension.
   extern template class allocator<char>;
   extern template class allocator<wchar_t>;
-#ifdef __USE_MALLOC
+
+#ifdef _GLIBCPP_USE_MALLOC
+  extern const int __node_allocator_is_malloc_alloc_template;
+  static const int* __node_allocator = &__node_allocator_is_malloc_alloc_template;
   extern template class __malloc_alloc_template<0>;
 #else
+  extern const int __node_allocator_is_default_alloc_template;
+  static const int* __node_allocator = &__node_allocator_is_default_alloc_template;
   extern template class __default_alloc_template<true,0>;
 #endif
 } // namespace std


More information about the Libstdc++ mailing list