【Glibc 源码分析】Glibc 2.23 -- malloc.c (第一部分 1 → 1081)

源码来自:https://elixir.bootlin.com/glibc/glibc-2.23/source/malloc/malloc.c

行数 1 → 279

简介

/* Malloc implementation for multiple threads without lock contention.
   [译]Malloc实现适用于没有锁争用的多个线程。[/译]
   Copyright (C) 1996-2016 Free Software Foundation, Inc.
   [译]版权所有(C) 1996-2016 Free Software Foundation, Inc.[/译]
   This file is part of the GNU C Library.
   [译]这个文件是GNU C库的一部分。[/译]
   Contributed by Wolfram Gloger <wg@malloc.de>
   and Doug Lea <dl@cs.oswego.edu>, 2001.
   [译]由 Wolfram Gloger <wg@malloc.de> 和 Doug Lea <dl@cs.oswego.edu> 在 2001 年提供[/译]

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public License as
   published by the Free Software Foundation; either version 2.1 of the
   License, or (at your option) any later version.
   [译]GNU C 库是一款自由软件;你可以重新分配它或者根据由 Free Software Foundation 出版的 2.1 版本许可中的 GNU Lesser General Public License 许可对其进行修改,或(由您选择)任何更新版本。[/译]

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
   [译]发行 GNU C 库的目的是希望它是有用的,但是它没有任何的保证;甚至连默示保证都没有,用于特定目的的适销性或适用性。有关更多细节,请参阅 GNU Lesser General Public License。[/译]

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If
   not, see <http://www.gnu.org/licenses/>.
   [译]你应该已经收到一份 GNU Lesser General Public 的副本许可证及GNU C库;请参阅文件 COPYING.LIB。 如果没有,请参见 <http://www.gnu.org/licenses/>。[/译]  */

/*
  This is a version (aka ptmalloc2) of malloc/free/realloc written by
  Doug Lea and adapted to multiple threads/arenas by Wolfram Gloger.
  [译]这是由 Doug Lea 编写的一个 malloc / free / realloc 的 aka ptmalloc2 版本,由 Wolfram Gloger 改编从而适应了 multiple threads 与 multiple arenas。[/译]

  There have been substantial changes made after the integration into
  glibc in all parts of the code.  Do not look for much commonality
  with the ptmalloc2 version.
  [译]在集成到 glibc 之后,代码中的所有部分都进行了重大更改。
  在 ptmalloc2 版本中不用寻找太多的共性。[/译]

版本

* Version ptmalloc2-20011215
  based on:
  VERSION 2.7.0 Sun Mar 11 14:14:06 2001  Doug Lea  (dl at gee)
[译]
* 版本 ptmalloc2-20011215
  基于:
  版本 2.7.0 2001 年 3 月 11 日星期日 14:14:06 Doug Lea(dl在gee)
[/译]

快速入门

* Quickstart
[译]* 快速入门[/译]

  In order to compile this implementation, a Makefile is provided with
  the ptmalloc2 distribution, which has pre-defined targets for some
  popular systems (e.g. "make posix" for Posix threads).  All that is
  typically required with regard to compiler flags is the selection of
  the thread package via defining one out of USE_PTHREADS, USE_THR or
  USE_SPROC.  Check the thread-m.h file for what effects this has.
  Many/most systems will additionally require USE_TSD_DATA_HACK to be
  defined, so this is the default for "make posix".
  [译]为了编译此实现,ptmalloc2 发行版提供了一个 Makefile,该发行版具有一些流行系统的预定义目标(例如,Posix线程的 "make posix")。关于编译器标志,通常所需要做的只是通过定义 USE_PTHREADS,USE_THR 或 USE_SPROC 中的一个来选择线程包。[/译]

为什么要使用此 malloc

* Why use this malloc?
[译]* 为什么要使用此 malloc ?[/译]

  This is not the fastest, most space-conserving, most portable, or
  most tunable malloc ever written. However it is among the fastest
  while also being among the most space-conserving, portable and tunable.
  Consistent balance across these factors results in a good general-purpose
  allocator for malloc-intensive programs.
  [译]这不是有史以来最快,最节省空间,最可移植或最可调的 malloc。但是,它是最快的,同时也是最节省空间,最便携和可调节的。在这些因素之间保持一致的平衡可以为 malloc 密集型程序提供一个良好的通用分配器。[/译]

  The main properties of the algorithms are:
  * For large (>= 512 bytes) requests, it is a pure best-fit allocator,
    with ties normally decided via FIFO (i.e. least recently used).
  * For small (<= 64 bytes by default) requests, it is a caching
    allocator, that maintains pools of quickly recycled chunks.
  * In between, and for combinations of large and small requests, it does
    the best it can trying to meet both goals at once.
  * For very large requests (>= 128KB by default), it relies on system
    memory mapping facilities, if supported.
  [译]
  该算法的主要特性是:
   *对于大型的(> = 0x200 字节)请求,它会是一个最适合的分配器,通常通过 FIFO(即最近最少使用的方法)来确定联系。
   *对于小的请求(默认情况下,<= 0x40 字节),它会是一个缓存分配器,用于维护快速回收的块池。
   *在两者之间,以及对于大型和小型请求的组合,它可以尝试同时实现两个目标的最佳方法。
   *对于非常大的请求(默认情况下,> == 128KB 即 0x20000 字节),它取决于系统内存映射功能(如果支持)。
  [/译]

  For a longer but slightly out of date high-level description, see
     http://gee.cs.oswego.edu/dl/html/malloc.html
  [译]有关较长但稍微过时的高级描述,请参阅
     http://gee.cs.oswego.edu/dl/html/malloc.html[/译]

  You may already by default be using a C library containing a malloc
  that is  based on some version of this malloc (for example in
  linux). You might still want to use the one in this file in order to
  customize settings or to avoid overheads associated with library
  versions.
  [译]默认情况下,您可能已经使用了一个包含 malloc 的 C 库,该库基于这个 malloc 的某个版本(例如在 linux 中)。为了自定义设置或避免与库版本相关的开销,您可能仍要使用此文件中的文件。[/译]

内容

* Contents, described in more detail in "description of public routines" below.
[译]* 内容,在下面的"公共例程的描述"中有更详细的描述。[/译]

  Standard (ANSI/SVID/...)  functions:
    malloc(size_t n);
    calloc(size_t n_elements, size_t element_size);
    free(void* p);
    realloc(void* p, size_t n);
    memalign(size_t alignment, size_t n);
    valloc(size_t n);
    mallinfo()
    mallopt(int parameter_number, int parameter_value)
  [译]
  标准 (ANSI / SVID / ...) 函数:
    malloc(size_t n);
    calloc(size_t n_elements, size_t element_size);
    free(void* p);
    realloc(void* p, size_t n);
    memalign(size_t alignment, size_t n);
    valloc(size_t n);
    mallinfo()
    mallopt(int parameter_number, int parameter_value)
  [/译]

  Additional functions:
    independent_calloc(size_t n_elements, size_t size, void* chunks[]);
    independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
    pvalloc(size_t n);
    cfree(void* p);
    malloc_trim(size_t pad);
    malloc_usable_size(void* p);
    malloc_stats();
  [译]
  附加函数:
    independent_calloc(size_t n_elements, size_t size, void* chunks[]);
    independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]);
    pvalloc(size_t n);
    cfree(void* p);
    malloc_trim(size_t pad);
    malloc_usable_size(void* p);
    malloc_stats();
  [/译]

重要的统计数据

* Vital statistics:
[译]* 重要的统计数据:[/译]

  Supported pointer representation:       4 or 8 bytes
  Supported size_t  representation:       4 or 8 bytes
       Note that size_t is allowed to be 4 bytes even if pointers are 8.
       You can adjust this by defining INTERNAL_SIZE_T
  [译]
  支持的指针表示形式:4 或 8 个字节
  支持的 size_t 表示形式:4 或 8 个字节
       请注意,即使指针为 8 字节,size_t 也允许其为 4 个字节。
       您可以通过定义 INTERNAL_SIZE_T 来进行调整
  [/译]

  Alignment:                              2 * sizeof(size_t) (default)
       (i.e., 8 byte alignment with 4byte size_t). This suffices for
       nearly all current machines and C compilers. However, you can
       define MALLOC_ALIGNMENT to be wider than this if necessary.
  [译]
  对齐方式:
       2 * sizeof(size_t) (默认) (即使用 4 字节 size_t 对齐的 8 字节对齐方式)。
       这几乎适用于几乎所有当前的机器和 C 编译器。
       但如果需要,可以将 MALLOC_ALIGNMENT 定义为比这个值更宽的值。
  [/译]

  Minimum overhead per allocated chunk:   4 or 8 bytes
       Each malloced chunk has a hidden word of overhead holding size
       and status information.
  [译]
  每个分配的块的最小开销:4 或 8 个字节
  每个分配的块都有一个隐藏的字,表示开销保持大小和状态信息。
  [/译]

  Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)
			  8-byte ptrs:  24/32 bytes (including, 4/8 overhead)
  [译]
  最小分配大小:4 字节指针:16 字节(包括 4 个开销)
			  8 字节指针:24/32 字节(包括 4/8 的开销)
  [/译]

       When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
       ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
       needed; 4 (8) for a trailing size field and 8 (16) bytes for
       free list pointers. Thus, the minimum allocatable size is
       16/24/32 bytes.
       [译]
       释放块时,需要额外的 12 个字节(用于 4 字节的指针)
       或 20 个(用于 8 字节指针但只有 4 字节大小的情况)
       或 24 个(用于 8/8)字节。 尾随大小字段为 4(8),空闲列表指针为8(16)字节
       因此,最小可分配大小为 16/24/32 字节。
       [/译]

       Even a request for zero bytes (i.e., malloc(0)) returns a
       pointer to something of the minimum allocatable size.
       [译]
       即使是零字节请求,即malloc(0)
       也会返回指向最小可分配大小的指针。
       [/译]

       The maximum overhead wastage (i.e., number of extra bytes
       allocated than were requested in malloc) is less than or equal
       to the minimum size, except for requests >= mmap_threshold that
       are serviced via mmap(), where the worst case wastage is 2 *
       sizeof(size_t) bytes plus the remainder from a system page (the
       minimal mmap unit); typically 4096 or 8192 bytes.
       [译]
       最大开销浪费(即分配的额外字节数多于 malloc 中的请求)小于或等于最小大小
       但若是返回的值 >= mmap_threshold 是通过 mmap() 函数而来的,那么除外
       其中最糟糕的浪费是 2 * sizeof(size_t) 字节加上系统页面的其余部分
       (最小mmap单位);通常为 4096 或 8192 字节。
       [/译]

  Maximum allocated size:  4-byte size_t: 2^32 minus about two pages
			   8-byte size_t: 2^64 minus about two pages
  [译]
  最大分配大小: 4 字节 size_t:2 ^ 32 减去约两页
			   8 字节 size_t:2 ^ 64 减去约两页
  [/译]

       It is assumed that (possibly signed) size_t values suffice to
       represent chunk sizes. `Possibly signed' is due to the fact
       that `size_t' may be defined on a system as either a signed or
       an unsigned type. The ISO C standard says that it must be
       unsigned, but a few systems are known not to adhere to this.
       Additionally, even when size_t is unsigned, sbrk (which is by
       default used to obtain memory from system) accepts signed
       arguments, and may not be able to handle size_t-wide arguments
       with negative sign bit.  Generally, values that would
       appear as negative after accounting for overhead and alignment
       are supported only via mmap(), which does not have this
       limitation.
       [译]
       假设(可能带符号) size_t 的值足以表示块大小。
       可能带符号是由于"size_t"可能在系统中被定义为 signed 类型或者 unsigned 类型。
       ISO C 标准规定它必须是 unsigned 类型的,但已知有几个系统不遵守这一点。
       此外,即使 size_t 是 unsigned 类型的,sbrk(默认情况下用于从系统获取内存)也会接受类型是 signed 的参数,并且可能无法处理带负号的 size_t 范围的参数。
       [/译]

       Requests for sizes outside the allowed range will perform an optional
       failure action and then return null. (Requests may also
       also fail because a system is out of memory.)
       [译]
       请求超出允许范围的大小将执行可选的失败操作,然后返回 null。
       (由于系统内存不足,请求也可能失败。)
       [/译]

  Thread-safety: thread-safe
  [译]线程安全:线程的安全[/译]

  Compliance: I believe it is compliant with the 1997 Single Unix Specification
       Also SVID/XPG, ANSI C, and probably others as well.
  [译]
  合规性:我相信它符合 1997 年 Single Unix 规范
       还有 SVID / XPG,ANSI C,也可能还有其他。
  [/译]

编译时选项的概要

* Synopsis of compile-time options:
[译]*编译时选项的概要:[/译]

    People have reported using previous versions of this malloc on all
    versions of Unix, sometimes by tweaking some of the defines
    below. It has been tested most extensively on Solaris and Linux.
    People also report using it in stand-alone embedded systems.
    [译]
    人们已经报告了在所有先前版本的Unix上都使用此malloc的情况,
    有时是通过调整以下一些定义来实现的。
    它已经在 Solaris 和 Linux 上进行了最广泛的测试。
    人们还报告了在独立的嵌入式系统中使用它的情况。
    [/译]

    The implementation is in straight, hand-tuned ANSI C.  It is not
    at all modular. (Sorry!)  It uses a lot of macros.  To be at all
    usable, this code should be compiled using an optimizing compiler
    (for example gcc -O3) that can simplify expressions and control
    paths. (FAQ: some macros import variables as arguments rather than
    declare locals because people reported that some debuggers
    otherwise get confused.)
    [译]
    该实现采用直接手动调整的 ANSIC。它根本不是模块化的。(对不起!)它使用了很多宏。
    为了完全可用,应使用可简化表达式和控制路径的优化编译器(例如gcc -O3)来编译此代码。
    (常见问题解答:某些宏将变量作为参数导入,而不是声明局部变量,因为人们报告说某些调试器否则会引起混淆。)
    [/译]

    OPTION[译]选项[/译]         DEFAULT VALUE[译]默认值[/译]

    Compilation Environment options:[译]编译环境选项:[/译]

    HAVE_MREMAP                0

    Changing default word sizes:[译]更改默认字号:[/译]

    INTERNAL_SIZE_T            size_t
    MALLOC_ALIGNMENT           MAX (2 * sizeof(INTERNAL_SIZE_T),
				    __alignof__ (long double))

    Configuration and functionality options:[译]配置和功能选项:[/译]

    USE_PUBLIC_MALLOC_WRAPPERS NOT defined
    USE_MALLOC_LOCK            NOT defined
    MALLOC_DEBUG               NOT defined
    REALLOC_ZERO_BYTES_FREES   1
    TRIM_FASTBINS              0

    Options for customizing MORECORE:[译]定制 MORECORE 的选项:[/译]

    MORECORE                   sbrk
    MORECORE_FAILURE           -1
    MORECORE_CONTIGUOUS        1
    MORECORE_CANNOT_TRIM       NOT defined
    MORECORE_CLEARS            1
    MMAP_AS_MORECORE_SIZE      (1024 * 1024)

    Tuning options that are also dynamically changeable via mallopt:
    [译]调整选项也可以通过 mallopt 动态更改:[/译]

    DEFAULT_MXFAST             64 (for 32bit), 128 (for 64bit)
    DEFAULT_TRIM_THRESHOLD     128 * 1024
    DEFAULT_TOP_PAD            0
    DEFAULT_MMAP_THRESHOLD     128 * 1024
    DEFAULT_MMAP_MAX           65536

    There are several other #defined constants and macros that you
    probably don't want to touch unless you are extending or adapting malloc.
    [译]
    另外还有几个 #defined 常量和宏,您可能不想接触它们,除非您正在扩展或修改 malloc。
    [/译]*/

/*
  void* is the pointer type that malloc should say it returns
  [译]void * 是 malloc 应当返回的指针类型[/译]
*/

#ifndef void
#define void      void
#endif /*void*/

#include <stddef.h>   /* for size_t */
#include <stdlib.h>   /* for getenv(), abort() */
#include <unistd.h>   /* for __libc_enable_secure */

#include <malloc-machine.h>
#include <malloc-sysdep.h>

#include <atomic.h>
#include <_itoa.h>
#include <bits/wordsize.h>
#include <sys/sysinfo.h>

#include <ldsodefs.h>

#include <unistd.h>
#include <stdio.h>    /* needed for malloc_stats */
#include <errno.h>

#include <shlib-compat.h>

/* For uintptr_t.  */
#include <stdint.h>

/* For va_arg, va_start, va_end.  */
#include <stdarg.h>

/* For MIN, MAX, powerof2.  */
#include <sys/param.h>

/* For ALIGN_UP et. al.  */
#include <libc-internal.h>

调试

/*
  Debugging:[译]调试:[/译]

  Because freed chunks may be overwritten with bookkeeping fields, this
  malloc will often die when freed memory is overwritten by user
  programs.  This can be very effective (albeit in an annoying way)
  in helping track down dangling pointers.
  [译]
  因为释放的块可能会被 bookkeeping 字段覆盖
  所以当释放的内存被用户程序覆盖时,这个 malloc 通常会死亡
  这在帮助跟踪悬空指针方面非常有效(尽管很烦人)
  [/译]

  If you compile with -DMALLOC_DEBUG, a number of assertion checks are
  enabled that will catch more memory errors. You probably won't be
  able to make much sense of the actual assertion errors, but they
  should help you locate incorrectly overwritten memory.  The checking
  is fairly extensive, and will slow down execution
  noticeably. Calling malloc_stats or mallinfo with MALLOC_DEBUG set
  will attempt to check every non-mmapped allocated and free chunk in
  the course of computing the summmaries. (By nature, mmapped regions
  cannot be checked very much automatically.)
  [译]
  如果使用 -DMALLOC_DEBUG 进行编译,则会启用许多断言检查,这些断言检查将捕获更多的内存错误。 
  您可能无法充分理解实际的断言错误,但是它们应该可以帮助您找到错误地覆盖的内存。
  检查是相当广泛的,并且会明显降低执行速度。
  调用 MALLOC_DEBUG 设置的 malloc_stats 或 mallinfo 将尝试在计算摘要的过程中检查分配的每个非映射块和空闲块。
  (自然地,不能非常自动地检查出映射区域。)
  [/译]

  Setting MALLOC_DEBUG may also be helpful if you are trying to modify
  this code. The assertions in the check routines spell out in more
  detail the assumptions and invariants underlying the algorithms.
  [译]
  如果您试图修改此代码,则设置 MALLOC_DEBUG 也可能会有所帮助。
  检查例程中的断言更详细地阐明了算法基础上的假设和不变量。
  [/译]

  Setting MALLOC_DEBUG does NOT provide an automated mechanism for
  checking that all accesses to malloced memory stay within their
  bounds. However, there are several add-ons and adaptations of this
  or other mallocs available that do this.
  [译]
  设置 MALLOC_DEBUG 不会提供一种自动机制来检查对已分配内存的所有访问是否都在其范围之内。
  但是,有它的改编以及一些附加组件或其他可用的 malloc 能够提供这个功能。
  [/译]
*/

#ifndef MALLOC_DEBUG
#define MALLOC_DEBUG 0
#endif

行数 280 → 304

__malloc_assert 函数

源码:

#ifdef NDEBUG
# define assert(expr) ((void) 0)
#else
# define assert(expr) \
  ((expr)								      \
   ? ((void) 0)								      \
   : __malloc_assert (#expr, __FILE__, __LINE__, __func__))

extern const char *__progname;

static void
__malloc_assert (const char *assertion, const char *file, unsigned int line,
		 const char *function)
{
  (void) __fxprintf (NULL, "%s%s%s:%u: %s%sAssertion `%s' failed.\n",
		     __progname, __progname[0] ? ": " : "",
		     file, line,
		     function ? function : "", function ? ": " : "",
		     assertion);
  fflush (stderr);
  abort ();
}
#endif

作用:

专门用于 malloc 函数的报错,参数的含义分别是:

rdi:报错输出信息

rsi:报错函数所属文件

rdx:报错函数在文件中所处的行数

rcx:报错函数

可以参考如下例子:

0x7f779ba7d421 <sysmalloc+465>    call   __malloc_assert <0x7f779ba79280>
     rdi: 0x7f779bb8d190 ← sub    byte ptr [rdi + 0x6c], ch /* '(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' */
     rsi: 0x7f779bb89bc5 ← insd   dword ptr [rdi], dx /* 'malloc.c' */
     rdx: 0x95a
     rcx: 0x7f779bb8d9d8 (__func__.11510) ← jae    0x7f779bb8da53 /* 'sysmalloc' */

行数 305 → 505

INTERNAL_SIZE_T

/*
  INTERNAL_SIZE_T is the word-size used for internal bookkeeping
  of chunk sizes.
  [译]INTERNAL_SIZE_T 是用于内部 bookkeeping 块大小的字的大小。[/译]

  The default version is the same as size_t.
  [译]默认的版本与 size_t 是相同的。[/译]

  While not strictly necessary, it is best to define this as an
  unsigned type, even if size_t is a signed type. This may avoid some
  artificial size limitations on some systems.
  [译]
  尽管不是必要的,但最好将其定义为 unsigned 类型,即便 size_t是有符号类型也是如此。
  这可以避免某些在系统中人为的大小限制。
  [/译]

  On a 64-bit machine, you may be able to reduce malloc overhead by
  defining INTERNAL_SIZE_T to be a 32 bit `unsigned int' at the
  expense of not being able to handle more than 2^32 of malloced
  space. If this limitation is acceptable, you are encouraged to set
  this unless you are on a platform requiring 16byte alignments. In
  this case the alignment requirements turn out to negate any
  potential advantages of decreasing size_t word size.
  [译]
  在64位计算机上,您可以通过将 INTERNAL_SIZE_T 的变量类型定义为 32 位的 unsigned int来减少 malloc 开销,但代价是无法处理超过 2 ^ 32 的 malloc 空间。
  如果可以接受此限制,除非您在要求 16 字节对齐的平台上,否则建议您进行设置。 
  在这种情况下,对齐的要求最终使减小 size_t 的字大小的任何潜在优势都化为了乌有。
  [/译]

  Implementors: Beware of the possible combinations of:
     - INTERNAL_SIZE_T might be signed or unsigned, might be 32 or 64 bits,
       and might be the same width as int or as long
     - size_t might have different width and signedness as INTERNAL_SIZE_T
     - int and long might be 32 or 64 bits, and might be the same width
  To deal with this, most comparisons and difference computations
  among INTERNAL_SIZE_Ts should cast them to unsigned long, being
  aware of the fact that casting an unsigned int to a wider long does
  not sign-extend. (This also makes checking for negative numbers
  awkward.) Some of these casts result in harmless compiler warnings
  on some systems.
  [译]
  接口:谨防以下情况的可能组合:
     -INTERNAL_SIZE_T 的变量类型可能是 signed 或者是 unsigned的,
      可能是 32 位或 64 位,并且宽度可能与 int 相同或与 long 相同
      -size_t 的宽度和签名可能与 INTERNAL_SIZE_T 不同
     -int 和 long 可能是 32 或 64 位,并且可能是相同的宽度
  为了解决这个问题,INTERNAL_SIZE_T 之间的大多数比较和差值计算都应将它们强制转换为无符号长整数,并意识到将无符号int强制转换为较宽长整数不会对符号进行扩展的事实。
  (这也使检查负数变得很尴尬。)其中某些强制类型转换在某些系统上会导致无害的编译器警告。
  [/译]
*/

#ifndef INTERNAL_SIZE_T
#define INTERNAL_SIZE_T size_t
#endif

/* The corresponding word size */
#define SIZE_SZ                (sizeof(INTERNAL_SIZE_T))
/* [记]SIZE_SZ == sizeof(size_t)[/记] */

MALLOC_ALIGNMENT

/*
  MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks.
  It must be a power of two at least 2 * SIZE_SZ, even on machines
  for which smaller alignments would suffice. It may be defined as
  larger than this though. Note however that code and data structures
  are optimized for the case of 8-byte alignment.
  [译]
  MALLOC_ALIGNMENT 是 malloc 分配的块时最小的对齐方式。
  即使对于更小的对齐方式都足以适应的机器,它的大小也必须是 2 的幂次数,而且它的大小至少为 2 * SIZE_SZ 。
  但是,你可以将其定义为大于此值。 但是请注意,代码和数据结构针对 8 字节对齐的情况进行了优化。
  [/译]
*/


#ifndef MALLOC_ALIGNMENT
# if !SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_16)
/* This is the correct definition when there is no past ABI to constrain it.
    [译]当没有过去的 ABI 约束时,这是正确的定义。[/译]

   Among configurations with a past ABI constraint, it differs from
   2*SIZE_SZ only on powerpc32.  For the time being, changing this is
   causing more compatibility problems due to malloc_get_state and
   malloc_set_state than will returning blocks not adequately aligned for
   long double objects under -mlong-double-128. 
   [译]
   在过去具有 ABI 约束的配置中,2 * SIZE_SZ 的值与其他架构不同的情况只出现在 powerpc32 架构上
   就目前而言,由于 malloc_get_state 和 malloc_set_state 的存在,对于在 -mlong-double-128 下返回未充分对齐的堆块,同时也是 long double 变量类型的对象,更改此参数将导致更多的兼容性问题。
   [/译]*/

#  define MALLOC_ALIGNMENT       (2 *SIZE_SZ < __alignof__ (long double)      \
                                  ? __alignof__ (long double) : 2 *SIZE_SZ)
# else
#  define MALLOC_ALIGNMENT       (2 *SIZE_SZ)
# endif
#endif
/* [记]
这里是为了兼容用老版本的 glibc 生成的程序,问队内师傅说这里判断的是 glibc 的符号版本,这个代码的意思是:
    判断该 GLIBC 是否是在 GLIBC_2.0 版本中引入,且在 GLIBC_2.16 版本中被淘汰,
    如果是就返回 1,不是就返回 0,也就是说如果没有旧版本的 GLIBC,
    那么就会通过如下方式设置 MALLOC_ALIGNMENT 的值(一种动态分配机制):
        判断 long double 变量类型在内存中的对齐方式,
        如果对齐所需的字节数大于 2 * sizeof(size_t),
        那么 MALLOC_ALIGNMENT 就等于 long double 变量类型的变量
        对齐所需的字节数大小,否则就等于 2 * sizeof(size_t)
    如果有旧版本的 GLIBC 的符号版本的话,那么 MALLOC_ALIGNMENT  的值
    就默认设置为 2 * sizeof(size_t)
[/记] */

/* The corresponding bit mask value */
/* [译]对应的位掩码值[/译] */
#define MALLOC_ALIGN_MASK      (MALLOC_ALIGNMENT - 1)

REALLOC_ZERO_BYTES_FREES

/*
  REALLOC_ZERO_BYTES_FREES should be set if a call to
  realloc with zero bytes should be the same as a call to free.
  This is required by the C standard. Otherwise, since this malloc
  returns a unique pointer for malloc(0), so does realloc(p, 0).
  [译]
  如果想要使对 realloc 的零字节的调用与对free的调用等价,则应该设置 REALLOC_ZERO_BYTES_FREES  变量。
  这是C标准所必需的。
  否则,由于此 malloc 会返回一个 malloc(0) 的惟一指针,所以 realloc(p, 0) 也是如此。
  [/译]
*/

#ifndef REALLOC_ZERO_BYTES_FREES
#define REALLOC_ZERO_BYTES_FREES 1
#endif
/* [记]
这块可以在自己编译 so 的时候把 REALLOC_ZERO_BYTES_FREES 的值改成 0,realloc(p, 0) 所做的事应该就会从 free(p) 变成 malloc(0)
[/记] */

TRIM_FASTBINS

/*
  TRIM_FASTBINS controls whether free() of a very small chunk can
  immediately lead to trimming. Setting to true (1) can reduce memory
  footprint, but will almost always slow down programs that use a lot
  of small chunks.
  [译]
  TRIM_FASTBINS 变量控制当 free() 很小的块的时候是否可以立即导致堆块合并。
  将 TRIM_FASTBINS 变量的值设置为 true,即 1
  可以减少内存占用,但是几乎总会降低那些使用很多小堆块的程序的速度。
  [/译]

  Define this only if you are willing to give up some speed to more
  aggressively reduce system-level memory footprint when releasing
  memory in programs that use many small chunks.  You can get
  essentially the same effect by setting MXFAST to 0, but this can
  lead to even greater slowdowns in programs using many small chunks.
  TRIM_FASTBINS is an in-between compile-time option, that disables
  only those chunks bordering topmost memory from being placed in
  fastbins.
  [译]
  只有当您愿意在释放使用许多小堆块的程序中的内存时,为了更积极地减少系统级内存占用而放弃一些速度时,才能定义它。
  通过将 MXFAST 设置为 0,基本上您可以获得相同的效果,但是这可能导致使用许多小块的程序的速度进一步降低。
  TRIM_FASTBINS 是介于编译时之间的选项,它仅禁止将与顶部内存接壤的那些堆块放入 fastbin 中。
  [/译]
*/

#ifndef TRIM_FASTBINS
#define TRIM_FASTBINS  0
#endif

MORECORE

/* Definition for getting more memory from the OS.  */
/* [译]用于从操作系统获取更多内存的定义[/译]  */
#define MORECORE         (*__morecore)
#define MORECORE_FAILURE 0
void * __default_morecore (ptrdiff_t);
void *(*__morecore)(ptrdiff_t) = __default_morecore;


#include <string.h>

/*
  MORECORE-related declarations. By default, rely on sbrk
  [译]与 MORECORE 相关的声明。 默认情况下,依靠 sbrk[/译]
*/


/*
  MORECORE is the name of the routine to call to obtain more memory
  from the system.  See below for general guidance on writing
  alternative MORECORE functions, as well as a version for WIN32 and a
  sample version for pre-OSX macos.
  [译]
  MORECORE 是要从系统获取更多内存的例程的名称。
  有关编写替代的 MORECORE 函数的一般指导,请参见下面的内容,
  以及 WIN32 的版本和 OSX 之前的 macOS 的示例版本。
  [/译]
*/

#ifndef MORECORE
#define MORECORE sbrk
#endif

MORECORE_FAILURE

/*
  MORECORE_FAILURE is the value returned upon failure of MORECORE
  as well as mmap. Since it cannot be an otherwise valid memory address,
  and must reflect values of standard sys calls, you probably ought not
  try to redefine it.
  [译]
  MORECORE_FAILURE 是 MORECORE 和 mmap 失败时返回的值。
  由于它不能是其他有效的内存地址,并且必须反映标准sys调用的值,
  因此您可能不应尝试重新定义它。
  [/译]
*/

#ifndef MORECORE_FAILURE
#define MORECORE_FAILURE (-1)
#endif

MORECORE_CONTIGUOUS

/*
  If MORECORE_CONTIGUOUS is true, take advantage of fact that
  consecutive calls to MORECORE with positive arguments always return
  contiguous increasing addresses.  This is true of unix sbrk.  Even
  if not defined, when regions happen to be contiguous, malloc will
  permit allocations spanning regions obtained from different
  calls. But defining this when applicable enables some stronger
  consistency checks and space efficiencies.
  [译]
  如果 MORECORE_CONTIGUOUS 为 true,请利用以下事实:
  对带有正参数的 MORECORE 的连续调用始终会返回连续的递增地址。
  Unix sbrk 确实如此。 即使没有定义,当区域碰巧是连续的时,
  malloc也会允许分配跨越从不同调用获得的区域的分配。
  但是在适用时对其进行定义可以实现更强的一致性检查和空间效率。
  [/译]
*/

#ifndef MORECORE_CONTIGUOUS
#define MORECORE_CONTIGUOUS 1
#endif

MORECORE_CANNOT_TRIM

/*
  Define MORECORE_CANNOT_TRIM if your version of MORECORE
  cannot release space back to the system when given negative
  arguments. This is generally necessary only if you are using
  a hand-crafted MORECORE function that cannot handle negative arguments.
  [译]
  如果在给定负参数时,您的 MORECORE 版本无法将空间释放回系统,
  则定义 MORECORE_CANNOT_TRIM。
  仅在使用无法处理否定参数的手工 MORECORE 函数时,通常才需要这样做。
  [/译]
*/

/* #define MORECORE_CANNOT_TRIM */

MORECORE_CLEARS

/*  MORECORE_CLEARS           (default 1)
     The degree to which the routine mapped to MORECORE zeroes out
     memory: never (0), only for newly allocated space (1) or always
     (2).  The distinction between (1) and (2) is necessary because on
     some systems, if the application first decrements and then
     increments the break value, the contents of the reallocated space
     are unspecified.
     [译]
     例程按映射到 MORECORE 的程度将内存清零:
         (0) 从不
         (1) 仅对于新分配的空间
         (2) 始终对
     (1) 和 (2) 之间的区别是必要的,因为在某些系统上,
     如果应用程序先递减然后增加 break 值,则未指定重新分配空间的内容。
     [/译]
 */

#ifndef MORECORE_CLEARS
# define MORECORE_CLEARS 1
#endif

MMAP_AS_MORECORE_SIZE

/*
   MMAP_AS_MORECORE_SIZE is the minimum mmap size argument to use if
   sbrk fails, and mmap is used as a backup.  The value must be a
   multiple of page size.  This backup strategy generally applies only
   when systems have "holes" in address space, so sbrk cannot perform
   contiguous expansion, but there is still space available on system.
   On systems for which this is known to be useful (i.e. most linux
   kernels), this occurs only when programs allocate huge amounts of
   memory.  Between this, and the fact that mmap regions tend to be
   limited, the size should be large, to avoid too many mmap calls and
   thus avoid running out of kernel resources.
   [译]
   MMAP_AS_MORECORE_SIZE 是 sbrk 失败时使用的大小为最小的 mmap 的参数,
   并且用作 mmap 的备份。 该值必须是页面大小的倍数。 
   此备份策略通常仅在系统在地址空间中存在“漏洞”时才适用,因此 sbrk 无法执行连续扩展,
   但是系统上仍有可用空间。 在已知对此有用的系统(即大多数 Linux 内核)上,
   仅当程序分配大量内存时才会发生这种情况。 在这之间以及mmap区域趋于受限的事实,
   其大小应较大,以避免太多的 mmap 调用,从而避免耗尽内核资源。
   [/译]
*/

#ifndef MMAP_AS_MORECORE_SIZE
#define MMAP_AS_MORECORE_SIZE (1024 * 1024)
#endif
[记]MMAP_AS_MORECORE_SIZE 的大小为 0x100000[/记]

HAVE_MREMAP

/*
  Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
  large blocks.
  [译]定义 HAVE_MREMAP 使 realloc() 函数在重新分配大块的时候使用 mremap() 函数。[/译]
*/

#ifndef HAVE_MREMAP
#define HAVE_MREMAP 0
#endif

行数 506 → 1081

公共函数的声明

前言

/*
  This version of malloc supports the standard SVID/XPG mallinfo
  routine that returns a struct containing usage properties and
  statistics. It should work on any SVID/XPG compliant system that has
  a /usr/include/malloc.h defining struct mallinfo. (If you'd like to
  install such a thing yourself, cut out the preliminary declarations
  as described above and below and save them in a malloc.h file. But
  there's no compelling reason to bother to do this.)
  [译]
  此版本的 malloc 支持 mallinfo 例程中的 SVID / XPG 标准,
  该例程返回包含使用情况属性和统计信息的结构。
  它应可在任何具有 /usr/include/malloc.h 定义 struct mallinfo 的
  SVID / XPG 兼容系统上工作。
  (如果您想自己安装这样的东西,请按照上面和下面的说明剪切初步的声明,
  然后将它们保存在 malloc.h 文件中。但是没有令人信服的理由去这样做。)
  [/译]
  The main declaration needed is the mallinfo struct that is returned
  (by-copy) by mallinfo().  The SVID/XPG malloinfo struct contains a
  bunch of fields that are not even meaningful in this version of
  malloc.  These fields are are instead filled by mallinfo() with
  other numbers that might be of interest.
  [译]
  所需的主要声明是由 mallinfo() (通过复制)返回的 mallinfo 结构。
  SVID/XPG 的 malloinfo 结构体包含了一堆字段,
  甚至这些字段在这个版本的 malloc 中是没有意义的。
  这些字段是由 mallinfo() 用其他数字(可能有趣的)填充的。
  [/译]
*/


/* ---------- description of public routines ------------ */
/* [译]公共函数的声明[/译] */

malloc(size_t n)

/*
  malloc(size_t n)
  Returns a pointer to a newly allocated chunk of at least n bytes, or null
  if no space is available. Additionally, on failure, errno is
  set to ENOMEM on ANSI C systems.
  [译]
  malloc(size_t n)
  返回一个指针,指向新分配的至少 n 个字节的块,如果没有空间可用,则返回 null。
  此外,在失败时,errno 在 ANSI C 系统上设置为 ENOMEM。
  [/译]

  If n is zero, malloc returns a minumum-sized chunk. (The minimum
  size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit
  systems.)  On most systems, size_t is an unsigned type, so calls
  with negative arguments are interpreted as requests for huge amounts
  of space, which will often fail. The maximum supported value of n
  differs across systems, but is in all cases less than the maximum
  representable value of a size_t.
  [译]
  如果 n 为零,malloc 返回一个最小大小的块。
  (大多数 32 位系统的最小大小是 16 字节,64 位系统的最小大小是 24 或 32 字节。)
  在大多数系统中,size_t 是无符号类型,
  因此带有负参数的调用被解释为对大量空间的请求,这通常会失败。
  n 的最大支持值在不同的系统中是不同的,但是在所有情况下都小于 size_t 的最大可表示值。
  [/译]
*/
void*  __libc_malloc(size_t);
libc_hidden_proto (__libc_malloc)

free(void* p)

/*
  free(void* p)
  Releases the chunk of memory pointed to by p, that had been previously
  allocated using malloc or a related routine such as realloc.
  It has no effect if p is null. It can have arbitrary (i.e., bad!)
  effects if p has already been freed.
  [译]
  释放 p 指向的内存块,该内存块先前已使用 malloc 或相关例程(例如 realloc)进行了分配。
  如果 p 为 null,则无效。 如果 p 已被释放,它可以具有任意(即不好)的效果。
  [/译]
  [记]
  这里不好的效果应该说的就是 double free 漏洞了
  轻则程序瘫痪,重则被人提权 2333
  [/记]

  Unless disabled (using mallopt), freeing very large spaces will
  when possible, automatically trigger operations that give
  back unused memory to the system, thus reducing program footprint.
  [译]
  除非禁用(使用 mallopt),否则在可能的情况下,释放非常大的空间将自动触发该操作:
      将未使用的内存返还给系统,从而减少程序占用空间。
  [/译]
*/
void     __libc_free(void*);
libc_hidden_proto (__libc_free)

calloc(size_t n_elements, size_t element_size);

/*
  calloc(size_t n_elements, size_t element_size);
  Returns a pointer to n_elements * element_size bytes, with all locations
  set to zero.
  [译]返回指向 n_elements * element_size 字节的指针,所有位置均设置为零。[/译]
*/
void*  __libc_calloc(size_t, size_t);

realloc(void* p, size_t n)

/*
  realloc(void* p, size_t n)
  Returns a pointer to a chunk of size n that contains the same data
  as does chunk p up to the minimum of (n, p's size) bytes, or null
  if no space is available.
  [译]
  返回一个指向大小为 n 的块的指针,该块包含与块p相同的数据,
  直到(p 的大小和 n 之间的最小值)个字节;如果没有可用空间,则返回null。
  [/译]

  The returned pointer may or may not be the same as p. The algorithm
  prefers extending p when possible, otherwise it employs the
  equivalent of a malloc-copy-free sequence.
  [译]
  返回的指针可能与 p 相同,也可能不相同。
  如果可能的话,算法倾向于扩展 p,否则它会使用与 malloca -copy-free 序列等价的值。
  [/译]

  If p is null, realloc is equivalent to malloc.
  [译]如果 p 为 null, realloc 就等于 malloc。[/译]

  If space is not available, realloc returns null, errno is set (if on
  ANSI) and p is NOT freed.
  [译]如果空间不可用,realloc 返回 null,设置 errno(如果在 ANSI 上),并且不释放 p。[/译]

  if n is for fewer bytes than already held by p, the newly unused
  space is lopped off and freed if possible.  Unless the #define
  REALLOC_ZERO_BYTES_FREES is set, realloc with a size argument of
  zero (re)allocates a minimum-sized chunk.
  [译]
  如果 n 的字节数少于 p 所保留的字节数,则可能会删除并释放新未使用的空间。
  除非设置了 #define REALLOC_ZERO_BYTES_FREES,
  否则该参数大小为零的 realloc 会分配(重新分配)一个最小大小的块。
  [/译]

  Large chunks that were internally obtained via mmap will always
  be reallocated using malloc-copy-free sequences unless
  the system supports MREMAP (currently only linux).
  [译]
  除非系统支持 MREMAP(目前只支持 linux),否则通过 mmap 内部获得的
  大块数据将始终使用 malloca -copy-free 序列进行重新分配。
  [/译]

  The old unix realloc convention of allowing the last-free'd chunk
  to be used as an argument to realloc is not supported.
  [译]
  不支持旧的 unix realloc 约定,即允许将无 last-free 的数据块用作 realloc 的参数。
  [/译]
*/
void*  __libc_realloc(void*, size_t);
libc_hidden_proto (__libc_realloc)

memalign(size_t alignment, size_t n);

/*
  memalign(size_t alignment, size_t n);
  Returns a pointer to a newly allocated chunk of n bytes, aligned
  in accord with the alignment argument.
  [译]
  memalign(size_t alignment, size_t n);
  返回一个指向新分配的 n 个字节的块的指针,该块按照 alignment 参数对齐。
  [/译]

  The alignment argument should be a power of two. If the argument is
  not a power of two, the nearest greater power is used.
  8-byte alignment is guaranteed by normal malloc calls, so don't
  bother calling memalign with an argument of 8 or less.
  [译]
  对齐参数应为 2 的幂。 如果参数不是 2 的幂,则使用最接近的更大的幂。
  正常的 malloc 调用保证了 8 字节的对齐,因此不要以小于等于 8 的参数来调用 memalign。
  [/译]

  Overreliance on memalign is a sure way to fragment space.
  [译]过度依赖 memalign 肯定会导致空间碎片化。[/译]
*/
void*  __libc_memalign(size_t, size_t);
libc_hidden_proto (__libc_memalign)

valloc(size_t n);

/*
  valloc(size_t n);
  Equivalent to memalign(pagesize, n), where pagesize is the page
  size of the system. If the pagesize is unknown, 4096 is used.
  [译]
  valloc(size_t n);
  相当于 memalign(pagesize, n),其中pagesize是系统的页面大小。
  如果 pagesize 未知,则使用 4096。
  [/译]
*/
void*  __libc_valloc(size_t);

mallopt(int parameter_number, int parameter_value)

/*
  mallopt(int parameter_number, int parameter_value)
  Sets tunable parameters The format is to provide a
  (parameter-number, parameter-value) pair.  mallopt then sets the
  corresponding parameter to the argument value if it can (i.e., so
  long as the value is meaningful), and returns 1 if successful else
  0.  SVID/XPG/ANSI defines four standard param numbers for mallopt,
  normally defined in malloc.h.  Only one of these (M_MXFAST) is used
  in this malloc. The others (M_NLBLKS, M_GRAIN, M_KEEP) don't apply,
  so setting them has no effect. But this malloc also supports four
  other options in mallopt. See below for details.  Briefly, supported
  parameters are as follows (listed defaults are for "typical"
  configurations).
  [译]
  mallopt(int parameter_number, int parameter_value)
  设置可调参数的格式是提供一个(参数-数字,参数-值)对。
  mallopt 然后将相应的参数设置为参数值(即,只要该值有意义),如果成功,则返回 1。
  SVID/XPG/ANSI 为 mallopt 定义了四个标准参数号,通常在 mallock .h 中定义。
  在这个 malloc 中只使用其中一个(M_MXFAST)。
  其他的(M_NLBLKS, M_GRAIN, M_KEEP)不适用,所以设置它们没有影响。
  但是这个 malloc 还支持 mallopt 中的其他四个选项。详见下文。
  简单地说,支持的参数如下(列出的默认值用于“典型”配置)。
  [/译]

  Symbol            param #   default    allowed param values
  M_MXFAST          1         64         0-80  (0 disables fastbins)
  M_TRIM_THRESHOLD -1         128*1024   any   (-1U disables trimming)
  M_TOP_PAD        -2         0          any
  M_MMAP_THRESHOLD -3         128*1024   any   (or 0 if no MMAP support)
  M_MMAP_MAX       -4         65536      any   (0 disables use of mmap)
*/
int      __libc_mallopt(int, int);
libc_hidden_proto (__libc_mallopt)

mallinfo()

/*
  mallinfo()
  Returns (by copy) a struct containing various summary statistics:
  [译]
  mallinfo()
  返回(通过副本)包含各种摘要统计信息的结构:
  [/译]

  arena:     current total non-mmapped bytes allocated from system
  ordblks:   the number of free chunks
  smblks:    the number of fastbin blocks (i.e., small chunks that
	       have been freed but not use resused or consolidated)
  hblks:     current number of mmapped regions
  hblkhd:    total bytes held in mmapped regions
  usmblks:   the maximum total allocated space. This will be greater
		than current total if trimming has occurred.
  fsmblks:   total bytes held in fastbin blocks
  uordblks:  current total allocated space (normal or mmapped)
  fordblks:  total free space
  keepcost:  the maximum number of bytes that could ideally be released
	       back to system via malloc_trim. ("ideally" means that
	       it ignores page restrictions etc.)
  [译]
  arena:     当前从系统分配的非映射字节总数
  ordblks:   空闲块的数量
  smblks:    fastbin 块的数量(即,已释放但未使用、重新使用或合并的小块)
  hblks:     当前映射区域的数目
  hblkhd:    在映射区域中保存的总字节数
  usmblks:   最大总分配空间。如果已经进行了调整,这个数字将大于当前的总数。
  fsmblks:   在 fastbin 块中保存的总字节数
  keepcost:  通过 malloc_trim 释放回系统的最大字节数。
	       ("理想情况下"意味着它忽略了页面限制等)
  [/译]

  Because these fields are ints, but internal bookkeeping may
  be kept as longs, the reported values may wrap around zero and
  thus be inaccurate.
  [译]
  因为这些字段是整数,但是内部的 bookkeeping 可能是 long 格式的,
  所以报告的值可能是 0,因此是不准确的。
  [/译]
*/
struct mallinfo __libc_mallinfo(void);

pvalloc(size_t n);

/*
  pvalloc(size_t n);
  Equivalent to valloc(minimum-page-that-holds(n)), that is,
  round up n to nearest pagesize.
  [译]
  pvalloc(size_t n);
  相当于 valloc(minimum-page-that-holds(n)),也就是说,将 n 四舍五入到最接近的页面大小。
  [/译]
 */
void*  __libc_pvalloc(size_t);

malloc_trim(size_t pad);

/*
  malloc_trim(size_t pad);

  If possible, gives memory back to the system (via negative
  arguments to sbrk) if there is unused memory at the `high' end of
  the malloc pool. You can call this after freeing large blocks of
  memory to potentially reduce the system-level memory requirements
  of a program. However, it cannot guarantee to reduce memory. Under
  some allocation patterns, some large free blocks of memory will be
  locked between two used chunks, so they cannot be given back to
  the system.
  [译]
  如果可能,如果在 malloc 池的“高”端有未使用的内存,则将内存返回给系统(通过对 sbrk 的负参数)。
  您可以在释放大量内存之后调用这个函数,以潜在地降低程序的系统级内存需求。
  但是,它不能保证减少内存。在某些分配模式下,一些大的空闲内存块将被锁定在两个已使用的块之间,因此它们不能返回给系统。
  [/译]

  The `pad' argument to malloc_trim represents the amount of free
  trailing space to leave untrimmed. If this argument is zero,
  only the minimum amount of memory to maintain internal data
  structures will be left (one page or less). Non-zero arguments
  can be supplied to maintain enough trailing space to service
  future expected allocations without having to re-obtain memory
  from the system.
  [译]
  malloc_trim 的'pad'参数表示未修剪的可用尾随空间量。
  如果这个参数为零,那么只剩下维护内部数据结构的最小内存数量(一个页面或更少)。
  可以提供非零参数来维护足够的尾随空间,从而为将来的预期分配提供服务,而不必从系统中重新获取内存。
  [/译]

  Malloc_trim returns 1 if it actually released any memory, else 0.
  On systems that do not support "negative sbrks", it will always
  return 0.
  [译]
  如果 Malloc_trim 实际释放了任何内存,则返回 1,否则返回 0。
  在不支持"负数 sbrks"的系统上,它将始终返回 0。
  [/译]
*/
int      __malloc_trim(size_t);

malloc_usable_size(void* p);(未完)

/*
  malloc_usable_size(void* p);

  Returns the number of bytes you can actually use in
  an allocated chunk, which may be more than you requested (although
  often not) due to alignment and minimum size constraints.
  You can use this many bytes without worrying about
  overwriting other allocated objects. This is not a particularly great
  programming practice. malloc_usable_size can be more useful in
  debugging and assertions, for example:
  [译]
  返回您在已分配块中实际可以使用的字节数
  由于对齐和最小大小的约束,该字节数可能大于您请求的字节数(尽管通常不是)
  您可以使用这么多字节,而不用担心会覆盖其他已分配的对象,这不是一个特别好的编程实践
  malloc_usable_size 在调试和断言中可能更有用,例如:
  [\译]

  p = malloc(n);
  assert(malloc_usable_size(p) >= 256);

*/
size_t   __malloc_usable_size(void*);

/*
  malloc_stats();
  Prints on stderr the amount of space obtained from the system (both
  via sbrk and mmap), the maximum amount (which may be more than
  current if malloc_trim and/or munmap got called), and the current
  number of bytes allocated via malloc (or realloc, etc) but not yet
  freed. Note that this is the number of bytes allocated, not the
  number requested. It will be larger than the number requested
  because of alignment and bookkeeping overhead. Because it includes
  alignment wastage as being in use, this figure may be greater than
  zero even when no user-level chunks are allocated.

  The reported current and maximum system memory can be inaccurate if
  a program makes other calls to system memory allocation functions
  (normally sbrk) outside of malloc.

  malloc_stats prints only the most commonly interesting statistics.
  More information can be obtained by calling mallinfo.

*/
void     __malloc_stats(void);

/*
  malloc_get_state(void);

  Returns the state of all malloc variables in an opaque data
  structure.
*/
void*  __malloc_get_state(void);

/*
  malloc_set_state(void* state);

  Restore the state of all malloc variables from data obtained with
  malloc_get_state().
*/
int      __malloc_set_state(void*);

/*
  posix_memalign(void **memptr, size_t alignment, size_t size);

  POSIX wrapper like memalign(), checking for validity of size.
*/
int      __posix_memalign(void **, size_t, size_t);

/* mallopt tuning options */

/*
  M_MXFAST is the maximum request size used for "fastbins", special bins
  that hold returned chunks without consolidating their spaces. This
  enables future requests for chunks of the same size to be handled
  very quickly, but can increase fragmentation, and thus increase the
  overall memory footprint of a program.

  This malloc manages fastbins very conservatively yet still
  efficiently, so fragmentation is rarely a problem for values less
  than or equal to the default.  The maximum supported value of MXFAST
  is 80. You wouldn't want it any higher than this anyway.  Fastbins
  are designed especially for use with many small structs, objects or
  strings -- the default handles structs/objects/arrays with sizes up
  to 8 4byte fields, or small strings representing words, tokens,
  etc. Using fastbins for larger objects normally worsens
  fragmentation without improving speed.

  M_MXFAST is set in REQUEST size units. It is internally used in
  chunksize units, which adds padding and alignment.  You can reduce
  M_MXFAST to 0 to disable all use of fastbins.  This causes the malloc
  algorithm to be a closer approximation of fifo-best-fit in all cases,
  not just for larger requests, but will generally cause it to be
  slower.
*/


/* M_MXFAST is a standard SVID/XPG tuning option, usually listed in malloc.h */
#ifndef M_MXFAST
#define M_MXFAST            1
#endif

#ifndef DEFAULT_MXFAST
#define DEFAULT_MXFAST     (64 * SIZE_SZ / 4)
#endif


/*
  M_TRIM_THRESHOLD is the maximum amount of unused top-most memory
  to keep before releasing via malloc_trim in free().

  Automatic trimming is mainly useful in long-lived programs.
  Because trimming via sbrk can be slow on some systems, and can
  sometimes be wasteful (in cases where programs immediately
  afterward allocate more large chunks) the value should be high
  enough so that your overall system performance would improve by
  releasing this much memory.

  The trim threshold and the mmap control parameters (see below)
  can be traded off with one another. Trimming and mmapping are
  two different ways of releasing unused memory back to the
  system. Between these two, it is often possible to keep
  system-level demands of a long-lived program down to a bare
  minimum. For example, in one test suite of sessions measuring
  the XF86 X server on Linux, using a trim threshold of 128K and a
  mmap threshold of 192K led to near-minimal long term resource
  consumption.

  If you are using this malloc in a long-lived program, it should
  pay to experiment with these values.  As a rough guide, you
  might set to a value close to the average size of a process
  (program) running on your system.  Releasing this much memory
  would allow such a process to run in memory.  Generally, it's
  worth it to tune for trimming rather tham memory mapping when a
  program undergoes phases where several large chunks are
  allocated and released in ways that can reuse each other's
  storage, perhaps mixed with phases where there are no such
  chunks at all.  And in well-behaved long-lived programs,
  controlling release of large blocks via trimming versus mapping
  is usually faster.

  However, in most programs, these parameters serve mainly as
  protection against the system-level effects of carrying around
  massive amounts of unneeded memory. Since frequent calls to
  sbrk, mmap, and munmap otherwise degrade performance, the default
  parameters are set to relatively high values that serve only as
  safeguards.

  The trim value It must be greater than page size to have any useful
  effect.  To disable trimming completely, you can set to
  (unsigned long)(-1)

  Trim settings interact with fastbin (MXFAST) settings: Unless
  TRIM_FASTBINS is defined, automatic trimming never takes place upon
  freeing a chunk with size less than or equal to MXFAST. Trimming is
  instead delayed until subsequent freeing of larger chunks. However,
  you can still force an attempted trim by calling malloc_trim.

  Also, trimming is not generally possible in cases where
  the main arena is obtained via mmap.

  Note that the trick some people use of mallocing a huge space and
  then freeing it at program startup, in an attempt to reserve system
  memory, doesn't have the intended effect under automatic trimming,
  since that memory will immediately be returned to the system.
*/

#define M_TRIM_THRESHOLD       -1

#ifndef DEFAULT_TRIM_THRESHOLD
#define DEFAULT_TRIM_THRESHOLD (128 * 1024)
#endif

/*
  M_TOP_PAD is the amount of extra `padding' space to allocate or
  retain whenever sbrk is called. It is used in two ways internally:

  * When sbrk is called to extend the top of the arena to satisfy
  a new malloc request, this much padding is added to the sbrk
  request.

  * When malloc_trim is called automatically from free(),
  it is used as the `pad' argument.

  In both cases, the actual amount of padding is rounded
  so that the end of the arena is always a system page boundary.

  The main reason for using padding is to avoid calling sbrk so
  often. Having even a small pad greatly reduces the likelihood
  that nearly every malloc request during program start-up (or
  after trimming) will invoke sbrk, which needlessly wastes
  time.

  Automatic rounding-up to page-size units is normally sufficient
  to avoid measurable overhead, so the default is 0.  However, in
  systems where sbrk is relatively slow, it can pay to increase
  this value, at the expense of carrying around more memory than
  the program needs.
*/

#define M_TOP_PAD              -2

#ifndef DEFAULT_TOP_PAD
#define DEFAULT_TOP_PAD        (0)
#endif

/*
  MMAP_THRESHOLD_MAX and _MIN are the bounds on the dynamically
  adjusted MMAP_THRESHOLD.
*/

#ifndef DEFAULT_MMAP_THRESHOLD_MIN
#define DEFAULT_MMAP_THRESHOLD_MIN (128 * 1024)
#endif

#ifndef DEFAULT_MMAP_THRESHOLD_MAX
  /* For 32-bit platforms we cannot increase the maximum mmap
     threshold much because it is also the minimum value for the
     maximum heap size and its alignment.  Going above 512k (i.e., 1M
     for new heaps) wastes too much address space.  */
# if __WORDSIZE == 32
#  define DEFAULT_MMAP_THRESHOLD_MAX (512 * 1024)
# else
#  define DEFAULT_MMAP_THRESHOLD_MAX (4 * 1024 * 1024 * sizeof(long))
# endif
#endif

/*
  M_MMAP_THRESHOLD is the request size threshold for using mmap()
  to service a request. Requests of at least this size that cannot
  be allocated using already-existing space will be serviced via mmap.
  (If enough normal freed space already exists it is used instead.)

  Using mmap segregates relatively large chunks of memory so that
  they can be individually obtained and released from the host
  system. A request serviced through mmap is never reused by any
  other request (at least not directly; the system may just so
  happen to remap successive requests to the same locations).

  Segregating space in this way has the benefits that:

   1. Mmapped space can ALWAYS be individually released back
      to the system, which helps keep the system level memory
      demands of a long-lived program low.
   2. Mapped memory can never become `locked' between
      other chunks, as can happen with normally allocated chunks, which
      means that even trimming via malloc_trim would not release them.
   3. On some systems with "holes" in address spaces, mmap can obtain
      memory that sbrk cannot.

  However, it has the disadvantages that:

   1. The space cannot be reclaimed, consolidated, and then
      used to service later requests, as happens with normal chunks.
   2. It can lead to more wastage because of mmap page alignment
      requirements
   3. It causes malloc performance to be more dependent on host
      system memory management support routines which may vary in
      implementation quality and may impose arbitrary
      limitations. Generally, servicing a request via normal
      malloc steps is faster than going through a system's mmap.

  The advantages of mmap nearly always outweigh disadvantages for
  "large" chunks, but the value of "large" varies across systems.  The
  default is an empirically derived value that works well in most
  systems.


  Update in 2006:
  The above was written in 2001. Since then the world has changed a lot.
  Memory got bigger. Applications got bigger. The virtual address space
  layout in 32 bit linux changed.

  In the new situation, brk() and mmap space is shared and there are no
  artificial limits on brk size imposed by the kernel. What is more,
  applications have started using transient allocations larger than the
  128Kb as was imagined in 2001.

  The price for mmap is also high now; each time glibc mmaps from the
  kernel, the kernel is forced to zero out the memory it gives to the
  application. Zeroing memory is expensive and eats a lot of cache and
  memory bandwidth. This has nothing to do with the efficiency of the
  virtual memory system, by doing mmap the kernel just has no choice but
  to zero.

  In 2001, the kernel had a maximum size for brk() which was about 800
  megabytes on 32 bit x86, at that point brk() would hit the first
  mmaped shared libaries and couldn't expand anymore. With current 2.6
  kernels, the VA space layout is different and brk() and mmap
  both can span the entire heap at will.

  Rather than using a static threshold for the brk/mmap tradeoff,
  we are now using a simple dynamic one. The goal is still to avoid
  fragmentation. The old goals we kept are
  1) try to get the long lived large allocations to use mmap()
  2) really large allocations should always use mmap()
  and we're adding now:
  3) transient allocations should use brk() to avoid forcing the kernel
     having to zero memory over and over again

  The implementation works with a sliding threshold, which is by default
  limited to go between 128Kb and 32Mb (64Mb for 64 bitmachines) and starts
  out at 128Kb as per the 2001 default.

  This allows us to satisfy requirement 1) under the assumption that long
  lived allocations are made early in the process' lifespan, before it has
  started doing dynamic allocations of the same size (which will
  increase the threshold).

  The upperbound on the threshold satisfies requirement 2)

  The threshold goes up in value when the application frees memory that was
  allocated with the mmap allocator. The idea is that once the application
  starts freeing memory of a certain size, it's highly probable that this is
  a size the application uses for transient allocations. This estimator
  is there to satisfy the new third requirement.

*/

#define M_MMAP_THRESHOLD      -3

#ifndef DEFAULT_MMAP_THRESHOLD
#define DEFAULT_MMAP_THRESHOLD DEFAULT_MMAP_THRESHOLD_MIN
#endif

/*
  M_MMAP_MAX is the maximum number of requests to simultaneously
  service using mmap. This parameter exists because
  some systems have a limited number of internal tables for
  use by mmap, and using more than a few of them may degrade
  performance.

  The default is set to a value that serves only as a safeguard.
  Setting to 0 disables use of mmap for servicing large requests.
*/

#define M_MMAP_MAX             -4

#ifndef DEFAULT_MMAP_MAX
#define DEFAULT_MMAP_MAX       (65536)
#endif

#include <malloc.h>

#ifndef RETURN_ADDRESS
#define RETURN_ADDRESS(X_) (NULL)
#endif

/* On some platforms we can compile internal, not exported functions better.
   Let the environment provide a macro and define it to be empty if it
   is not available.  */
#ifndef internal_function
# define internal_function
#endif

/* Forward declarations.  */
struct malloc_chunk;
typedef struct malloc_chunk* mchunkptr;

/* Internal routines.  */

static void*  _int_malloc(mstate, size_t);
static void     _int_free(mstate, mchunkptr, int);
static void*  _int_realloc(mstate, mchunkptr, INTERNAL_SIZE_T,
			   INTERNAL_SIZE_T);
static void*  _int_memalign(mstate, size_t, size_t);
static void*  _mid_memalign(size_t, size_t, void *);

static void malloc_printerr(int action, const char *str, void *ptr, mstate av);

static void* internal_function mem2mem_check(void *p, size_t sz);
static int internal_function top_check(void);
static void internal_function munmap_chunk(mchunkptr p);
#if HAVE_MREMAP
static mchunkptr internal_function mremap_chunk(mchunkptr p, size_t new_size);
#endif

static void*   malloc_check(size_t sz, const void *caller);
static void      free_check(void* mem, const void *caller);
static void*   realloc_check(void* oldmem, size_t bytes,
			       const void *caller);
static void*   memalign_check(size_t alignment, size_t bytes,
				const void *caller);
#ifndef NO_THREADS
static void*   malloc_atfork(size_t sz, const void *caller);
static void      free_atfork(void* mem, const void *caller);
#endif

点赞
  1. TaQini说道:
    Firefox Ubuntu
    tql :zhenbang:
    1. binLep说道:
      Firefox Windows 10
      太难了 :huaji9: 为啥我显示你的回复是 5 月 8 号中午的,有毒 :huaji8:
      1. TaQini说道:
        WebView Android 9
        跨时空回复 :jingya:

发表评论

电子邮件地址不会被公开。必填项已用 * 标注