[PATCH] Slightly better way to __USE_MALLOC

Brad Spencer spencer@infointeractive.com
Tue Oct 8 14:11:00 GMT 2002


Hi, all..  When debugging recently, I found it necessary to use a 
__USE_MALLOCed version of the library.  Having followed the
discussions about this topic a while back, I was aware that doing this
is somewhat clumsy and (perhaps) error-prone.  After I had actually
rebuilt the library (and found my bug quite quickly with "mpatrol",
BTW), I decided that it might be useful to have a malloc-using version
of the library "hanging around".  Since "a patch would be
appreciated", here's one, albeit not a perfect one.

I'm no configure wizard, but I think I managed to hack together
a patch that creates a new "--enable-use-malloc=yes" feature.  I
changed __USE_MALLOC to be _GLIBCPP_USE_MALLOC in the process, and
eliminated the "#if defined" check in c++config because I think the
linker will always notice if you mismatch allocation mechanisms
between library and application.

To test this, I wrote a small program (before I renamed the macro):

#include <vector>
#include <iostream>

int
main()
{
  std::vector<int> x;
  
#ifdef __USE_MALLOC
  std::cout << "malloc use" << std::endl;
#else
  std::cout << "not malloc use" << std::endl;
#endif // __USE_MALLOC
  return 0;
}

Then, by compiling it four different ways, it seems like only the
valid combinations will link:

$ g++ -Wall -o foo1 foo.cc                               # Ok
$ g++ -Wall -D__USE_MALLOC -L$malloc_dir -o foo2 foo.cc  # Ok

$ g++ -Wall -D__USE_MALLOC -o foo3 foo.cc                # Errors; good
/tmp/ccHFHnA5.o: In function `std::__simple_alloc<int,
std::__malloc_alloc_template<(int)0> >::deallocate(int*, unsigned)':
/tmp/ccHFHnA5.o(.gnu.linkonce.t._ZNSt14__simple_allocIiSt23__malloc_alloc_templateILi0EEE10deallocateEPij+0x1d):
undefined reference to
`std::__malloc_alloc_template<(int)0>::deallocate(void*, unsigned)'
collect2: ld returned 1 exit status

$ g++ -Wall -L$malloc_dir -o foo4 foo.cc                 # Errors; good
/tmp/ccjemhTF.o: In function `std::__simple_alloc<int,
std::__default_alloc_template<(bool)1, (int)0> >::deallocate(int*,
unsigned)':
/tmp/ccjemhTF.o(.gnu.linkonce.t._ZNSt14__simple_allocIiSt24__default_alloc_templateILb1ELi0EEE10deallocateEPij+0x1d):
undefined reference to `std::__default_alloc_template<(bool)1,
(int)0>::deallocate(void*, unsigned)'
collect2: ld returned 1 exit status

Granted, the diagnostic is far from clear, but it does prevent use.
Perhaps a symbol named "__library_not_built_with_use_malloc" would
help? :)

I plan to use this with my build system to let me do something like

  g++ -D_GLIBCPP_USE_MALLOC -L$prefix/.../lib/debug

by placing a "use-malloc"-built version of the library in the debug
directory inside the compiler's installation.  Someone more familiar
with configure could probably make this happen automatically (by
building and installing the library twice) when --enable-use-malloc
was enabled (or perhaps set to "as-alternate" or something).

Caveat: I've likely patched at least one automatically generated file
:( in the diff I have attached.  Hopefully someone will point out if I
have.  But I did learn how to write a change log :)  This diff is
against the gcc-3.2 release version of libstdc++-v3.

2002-10-08  Brad Spencer <spencer@infointeractive.com>

        * acconfig.h, acinclude.m4, config.h.in, configure.in,
        include/backward/alloc.h, include/bits/c++config,
        include/bits/stl_alloc.h, src/stl-inst.cc: Changed
        __USE_MALLOC to _GLIBCPP_USE_MALLOC and added 
        --enable-use-malloc to configure.
        
-- 
------------------------------------------------------------------
Brad Spencer - spencer@infointeractive.com - "It's quite nice..."
Systems Architect | InfoInterActive Corp. | A Canadian AOL Company
-------------- next part --------------
*** ./acconfig.h	Fri Dec 14 17:06:32 2001
--- ../../../gcc-3.2/libstdc++-v3/./acconfig.h	Fri Oct  4 18:08:00 2002
***************
*** 37,42 ****
--- 37,45 ----
  // 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 
  
*** ./acinclude.m4	Wed Jul  3 19:47:34 2002
--- ../../../gcc-3.2/libstdc++-v3/./acinclude.m4	Fri Oct  4 18:08:25 2002
*************** fi
*** 2089,2094 ****
--- 2089,2123 ----
  
  
  dnl
+ dnl Check for whether the _GLIBCPP_USE_MALLOC macro should be defined and thus
+ dnl the library should be built in without the default allocator.
+ dnl
+ dnl GLIBCPP_ENABLE_USE_MALLOC
+ dnl --enable-use-malloc turns them on.
+ dnl --disable-use-malloc leaves them off.
+ dnl  +  Usage:  GLIBCPP_ENABLE_USE_MALLOC[(DEFAULT)]
+ dnl       Where DEFAULT is either `yes' or `no'.  If ommitted, it
+ dnl       defaults to `no'.
+ AC_DEFUN(GLIBCPP_ENABLE_USE_MALLOC, [dnl
+ define([GLIBCPP_ENABLE_USE_MALLOC_DEFAULT], ifelse($1, yes, yes, no))dnl
+ AC_ARG_ENABLE(use-malloc,
+ changequote(<<, >>)dnl
+ <<  --enable-use-malloc     use the slower malloc-based allocator [default=>>GLIBCPP_ENABLE_CONCEPT_CHECKS_DEFAULT],
+ changequote([, ])dnl
+ [case "$enableval" in
+  yes) enable_use_malloc=yes ;;
+  no)  enable_use_malloc=no ;;
+  *)   AC_MSG_ERROR([Unknown argument to enable/disable malloc allocator]) ;;
+  esac],
+ enable_use_malloc=GLIBCPP_ENABLE_USE_MALLOC_DEFAULT)dnl
+ dnl Option parsed, now set things appropriately
+ if test x"$enable_use_malloc" = xyes; then
+   AC_DEFINE(_GLIBCPP_USE_MALLOC)
+ fi
+ ])
+ 
+ 
+ dnl
  dnl Add version tags to symbols in shared library (or not), additionally
  dnl marking other symbols as private/local (or not).
  dnl
*** ./config.h.in	Mon May 27 12:01:29 2002
--- ../../../gcc-3.2/libstdc++-v3/./config.h.in	Fri Oct  4 18:08:05 2002
***************
*** 24,29 ****
--- 24,32 ----
  // 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
  
*** ./configure.in	Tue Oct  8 12:18:19 2002
--- ../../../gcc-3.2/libstdc++-v3/./configure.in	Fri Oct  4 18:03:50 2002
*************** GLIBCPP_ENABLE_CXX_FLAGS([none])
*** 56,61 ****
--- 56,62 ----
  GLIBCPP_ENABLE_SJLJ_EXCEPTIONS
  GLIBCPP_ENABLE_LIBUNWIND_EXCEPTIONS
  GLIBCPP_ENABLE_CONCEPT_CHECKS
+ GLIBCPP_ENABLE_USE_MALLOC        
  
  # Check for headers necessary for libsupc++ using dyn-string.c/cxa_demangle.c
  AC_CHECK_HEADERS(string.h stdlib.h)
*** ./include/backward/alloc.h	Thu Dec  6 16:29:30 2001
--- ../../../gcc-3.2/libstdc++-v3/./include/backward/alloc.h	Fri Oct  4 18:01:48 2002
*************** using std::__debug_alloc; 
*** 53,59 ****
  using std::__alloc; 
  using std::__single_client_alloc; 
  using std::allocator;
! #ifdef __USE_MALLOC
  using std::malloc_alloc; 
  #else
  using std::__default_alloc_template; 
--- 53,59 ----
  using std::__alloc; 
  using std::__single_client_alloc; 
  using std::allocator;
! #ifdef _GLIBCPP_USE_MALLOC
  using std::malloc_alloc; 
  #else
  using std::__default_alloc_template; 
*** ./include/bits/c++config	Wed Aug 14 04:16:24 2002
--- ../../../gcc-3.2/libstdc++-v3/./include/bits/c++config	Sat Oct  5 13:28:19 2002
***************
*** 69,80 ****
  // 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.
--- 69,77 ----
  // 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 _GLIBCPP_USE_MALLOC on the command line.
! // It must be defined at library-build time.
! // Configure the library to use malloc 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.
*** ./include/bits/stl_alloc.h	Fri Apr 19 05:28:15 2002
--- ../../../gcc-3.2/libstdc++-v3/./include/bits/stl_alloc.h	Fri Oct  4 18:01:48 2002
*************** namespace std
*** 199,205 ****
  
  
  // Determines the underlying allocator choice for the node allocator.
! #ifdef __USE_MALLOC
    typedef __malloc_alloc_template<0>  __mem_interface;
  #else
    typedef __new_alloc                 __mem_interface;
--- 199,205 ----
  
  
  // Determines the underlying allocator choice for the node allocator.
! #ifdef _GLIBCPP_USE_MALLOC
    typedef __malloc_alloc_template<0>  __mem_interface;
  #else
    typedef __new_alloc                 __mem_interface;
*************** namespace std
*** 284,290 ****
    };
  
  
! #ifdef __USE_MALLOC
  
  typedef __mem_interface __alloc;
  typedef __mem_interface __single_client_alloc;
--- 284,290 ----
    };
  
  
! #ifdef _GLIBCPP_USE_MALLOC
  
  typedef __mem_interface __alloc;
  typedef __mem_interface __single_client_alloc;
*************** template<bool __threads, int __inst>
*** 591,597 ****
    typedef __default_alloc_template<false, 0>   __single_client_alloc;
  
  
! #endif /* ! __USE_MALLOC */
  
  
  /**
--- 591,597 ----
    typedef __default_alloc_template<false, 0>   __single_client_alloc;
  
  
! #endif /* ! _GLIBCPP_USE_MALLOC */
  
  
  /**
*************** template<bool __threads, int __inst>
*** 599,605 ****
   *  "SGI" style.  (See comments at the top of stl_alloc.h.)
   *
   *  The underlying allocator behaves as follows.
!  *  - if __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)
--- 599,605 ----
   *  "SGI" style.  (See comments at the top of stl_alloc.h.)
   *
   *  The underlying allocator behaves as follows.
!  *  - 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)
*************** struct _Alloc_traits<_Tp, __malloc_alloc
*** 867,873 ****
    typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
  };
  
! #ifndef __USE_MALLOC
  template <class _Tp, bool __threads, int __inst>
  struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> >
  {
--- 867,873 ----
    typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
  };
  
! #ifndef _GLIBCPP_USE_MALLOC
  template <class _Tp, bool __threads, int __inst>
  struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> >
  {
*************** struct _Alloc_traits<_Tp, 
*** 899,905 ****
    typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
  };
  
! #ifndef __USE_MALLOC
  template <class _Tp, class _Tp1, bool __thr, int __inst>
  struct _Alloc_traits<_Tp, 
                        __allocator<_Tp1, 
--- 899,905 ----
    typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
  };
  
! #ifndef _GLIBCPP_USE_MALLOC
  template <class _Tp, class _Tp1, bool __thr, int __inst>
  struct _Alloc_traits<_Tp, 
                        __allocator<_Tp1, 
*************** struct _Alloc_traits<_Tp, __allocator<_T
*** 927,933 ****
    // NB: This syntax is a GNU extension.
    extern template class allocator<char>;
    extern template class allocator<wchar_t>;
! #ifdef __USE_MALLOC
    extern template class __malloc_alloc_template<0>;
  #else
    extern template class __default_alloc_template<true, 0>;
--- 927,933 ----
    // NB: This syntax is a GNU extension.
    extern template class allocator<char>;
    extern template class allocator<wchar_t>;
! #ifdef _GLIBCPP_USE_MALLOC
    extern template class __malloc_alloc_template<0>;
  #else
    extern template class __default_alloc_template<true, 0>;
*** ./src/stl-inst.cc	Fri Apr 19 05:28:18 2002
--- ../../../gcc-3.2/libstdc++-v3/./src/stl-inst.cc	Sat Oct  5 13:38:02 2002
*************** namespace std
*** 39,45 ****
    template class allocator<char>;
    template class allocator<wchar_t>;
  
! #ifdef __USE_MALLOC
    template class __malloc_alloc_template<0>;
  #else
    template class __default_alloc_template<true, 0>;
--- 39,47 ----
    template class allocator<char>;
    template class allocator<wchar_t>;
  
!   // This will cause linker errors if the user tries to mismatch
!   // an allocator-using program and library.  That is good.
! #ifdef _GLIBCPP_USE_MALLOC
    template class __malloc_alloc_template<0>;
  #else
    template class __default_alloc_template<true, 0>;


More information about the Libstdc++ mailing list