Does dynamic memory allocation differ in C and C++ in popular implementations?

后端 未结 5 846
情书的邮戳
情书的邮戳 2020-12-04 12:17

As far as the respective language standards go, C offers dynamic memory allocation only through the malloc() family, while in C++ the most common form of alloca

相关标签:
5条回答
  • 2020-12-04 12:24

    It's not a matter of performance: pA = new A has a different side effect than pA = (A*)malloc(sizeof(A));

    In the second one, the A's constructor is not called. To come to a same effect you should do

    pA = (A*)malloc(sizeof(A));
    new(pA)A();
    

    where new is the "placement new"...

    void* operator new(size_t sz, void* place) 
    { return place; }
    
    0 讨论(0)
  • 2020-12-04 12:33

    On Visual C++, stepping into a new expression leads me to this snippet in new.cpp:

    #include <cstdlib>
    #include <new>
    
    _C_LIB_DECL
    int __cdecl _callnewh(size_t size) _THROW1(_STD bad_alloc);
    _END_C_LIB_DECL
    
    void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
            {       // try to allocate size bytes
            void *p;
            while ((p = malloc(size)) == 0)
                    if (_callnewh(size) == 0)
                    {       // report no memory
                    static const std::bad_alloc nomem;
                    _RAISE(nomem);
                    }
    
            return (p);
            }
    

    So VC++'s new also wraps the malloc() call.

    0 讨论(0)
  • 2020-12-04 12:34

    glibc new operator is a thin wrapper around malloc. And glibc malloc uses different strategies for different size allocation requests. You can see the implementation, or at least the comments here.

    Here's an excerpt from the comments in malloc.c:

    /*
    47   This is not the fastest, most space-conserving, most portable, or
    48   most tunable malloc ever written. However it is among the fastest
    49   while also being among the most space-conserving, portable and tunable.
    50   Consistent balance across these factors results in a good general-purpose
    51   allocator for malloc-intensive programs.
    52 
    53   The main properties of the algorithms are:
    54   * For large (>= 512 bytes) requests, it is a pure best-fit allocator,
    55     with ties normally decided via FIFO (i.e. least recently used).
    56   * For small (<= 64 bytes by default) requests, it is a caching
    57     allocator, that maintains pools of quickly recycled chunks.
    58   * In between, and for combinations of large and small requests, it does
    59     the best it can trying to meet both goals at once.
    60   * For very large requests (>= 128KB by default), it relies on system
    61     memory mapping facilities, if supported.
    */
    
    0 讨论(0)
  • 2020-12-04 12:37

    In most implementations operator new() just calls malloc(). In fact even The Standard suggests that as a default stratege. Of course you can implement your own operator new, usually for a class if you want better performance, but the default is usually just calling malloc().

    0 讨论(0)
  • 2020-12-04 12:42

    Here is the implementation used by g++ 4.6.1:

    _GLIBCXX_WEAK_DEFINITION void *
    operator new (std::size_t sz) throw (std::bad_alloc)
    {
      void *p;
    
      /* malloc (0) is unpredictable; avoid it.  */
      if (sz == 0)
        sz = 1;
      p = (void *) malloc (sz);
      while (p == 0)
        {
          new_handler handler = __new_handler;
          if (! handler)
    #ifdef __EXCEPTIONS
            throw bad_alloc();
    #else
            std::abort();
    #endif
          handler ();
          p = (void *) malloc (sz);
        }
    
      return p;
    }
    

    This is found in libstdc++-v3/libsupc++/new_op.cc inside the g++ source distro.

    As you can see, it's a fairly thin wrapper around malloc.

    edit On many systems it is possible to fine-tune the behaviour of malloc, typically by calling mallopt or setting environment variables. Here is one article discussing some features available on Linux.

    According to Wikipedia, glibc versions 2.3+ use a modified version of the allocator called ptmalloc, which itself is a derivative of dlmalloc designed by Doug Lea. Interestingly, in an article about dlmalloc Doug Lea gives the following perspective (emphasis mine):

    I wrote the first version of the allocator after writing some C++ programs that almost exclusively relied on allocating dynamic memory. I found that they ran much more slowly and/or with much more total memory consumption than I expected them to. This was due to characteristics of the memory allocators on the systems I was running on (mainly the then-current versions of SunOs and BSD ). To counter this, at first I wrote a number of special-purpose allocators in C++, normally by overloading operator new for various classes. Some of these are described in a paper on C++ allocation techniques that was adapted into the 1989 C++ Report article Some storage allocation techniques for container classes.

    However, I soon realized that building a special allocator for each new class that tended to be dynamically allocated and heavily used was not a good strategy when building kinds of general-purpose programming support classes I was writing at the time. (From 1986 to 1991, I was the the primary author of libg++ , the GNU C++ library.) A broader solution was needed -- to write an allocator that was good enough under normal C++ and C loads so that programmers would not be tempted to write special-purpose allocators except under very special conditions.

    This article presents a description of some of the main design goals, algorithms, and implementation considerations for this allocator.

    0 讨论(0)
提交回复
热议问题