在流行的实现中,动态内存分配在C和C ++中有所不同?

就相应的语言标准而言,C仅通过malloc()系列提供动态内存分配,而在C ++中,最常见的分配形式由::operator new() 。 C风格的malloc也可以在C ++中使用,许多“宝宝的第一个分配器”的例子都将它用作它的核心分配函数,但我很好奇当代编译器如何实现实际的生产操作符 - 新。

它仅仅是一个围绕malloc()简单包装,还是因为与典型的C程序相比,典型的C ++程序存在相当不同的内存分配行为,从根本上实现了它?

[编辑:我认为主要区别通常描述如下:AC程序具有更少,更大,更长时间的分配,而C ++程序具有许多小的短暂分配。 如果这是错误的,请随意加入,但听起来好像考虑到这一点会受益。]

对于像GCC这样的编译器来说,只需要一个单独的核心分配实现并将其用于所有相关语言就很容易,所以我想知道是否有细节上的差异会试图优化每种语言的结果分配性能。


更新:感谢所有伟大的答案! 它看起来像在GCC中完全由ptmalloc解决,MSVC也在核心使用malloc 。 有谁知道MSVC-malloc是如何实现的?


这是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;
}

这可以在g ++源代码发行版的libstdc++-v3/libsupc++/new_op.cc

正如你所看到的,这是一个相当薄的malloc包装。

编辑在许多系统上,可以通过调用mallopt或设置环境变量来微调malloc的行为。 这里有一篇文章讨论Linux上的一些功能。

根据维基百科, glibc版本2.3+使用分配器的修改版本,称为ptmalloc ,它本身是由Doug Lea设计的dlmalloc的衍生产品。 有趣的是,在一篇关于dlmalloc的文章中,Doug Lea给出了下面的观点(重点是我的):

在编写几乎完全依赖分配动态内存的C ++程序之后,我编写了分配器的第一个版本。 我发现他们的运行速度要慢得多,而且总的内存消耗比我预期的要多得多。 这是由于我运行的系统上的内存分配器的特性(主要是当时最新版本的SunO和BSD)。 为了解决这个问题,起初我用C ++编写了一些特殊用途的分配器,通常是通过重载运算符new来为不同的类使用。 其中一些内容在有关C ++分配技术的论文中进行了描述,这些技术已适用于1989年C ++报告文章中有关容器类的一些存储分配技术。

但是,我很快就意识到,为每个新类设置一个专门的分配器,这种分配器往往是动态分配和大量使用的,在我编写当时编写的各种通用编程支持类时,并不是一个好策略。 (从1986年到1991年,我是libg ++的主要作者,GNU C ++库)。需要一个更广泛的解决方案 - 编写一个在正常C ++和C加载下足够好的分配器,这样程序员就不会受到诱惑编写特殊用途的分配器,除非在特殊条件下。

本文介绍了该分配器的一些主要设计目标,算法和实现注意事项。


在大多数实现中, operator new()只是调用malloc() 。 事实上,即使标准建议作为默认策略。 当然,如果你想要更好的性能,你可以实现自己的operator new ,通常是为了一个类,但默认情况下通常只调用malloc()


glibc new操作符是malloc的一个薄包装器。 而glibc malloc针对不同的大小分配请求使用不同的策略。 你可以看到实现,或者至少在这里的评论。

以下是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.
*/
链接地址: http://www.djcxy.com/p/78717.html

上一篇: Does dynamic memory allocation differ in C and C++ in popular implementations?

下一篇: dynamically allocated memory after program termination