📄 dlmalloc.c
字号:
#define set_inuse(p)\((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE#define clear_inuse(p)\((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)/* check/set/clear inuse bits in known places */#define inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)#define set_inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)#define clear_inuse_bit_at_offset(p, s)\ (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))/* Dealing with size fields*//* Get size, ignoring use bits */#define chunksize(p) ((p)->size & ~(SIZE_BITS))/* Set size at head, without disturbing its use bit */#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s)))/* Set size/use ignoring previous bits in header */#define set_head(p, s) ((p)->size = (s))/* Set size at footer (only when chunk is not in use) */#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))/* Bins The bins, `av_' are an array of pairs of pointers serving as the heads of (initially empty) doubly-linked lists of chunks, laid out in a way so that each pair can be treated as if it were in a malloc_chunk. (This way, the fd/bk offsets for linking bin heads and chunks are the same). Bins for sizes < 512 bytes contain chunks of all the same size, spaced 8 bytes apart. Larger bins are approximately logarithmically spaced. (See the table below.) The `av_' array is never mentioned directly in the code, but instead via bin access macros. Bin layout: 64 bins of size 8 32 bins of size 64 16 bins of size 512 8 bins of size 4096 4 bins of size 32768 2 bins of size 262144 1 bin of size what's left There is actually a little bit of slop in the numbers in bin_index for the sake of speed. This makes no difference elsewhere. The special chunks `top' and `last_remainder' get their own bins, (this is implemented via yet more trickery with the av_ array), although `top' is never properly linked to its bin since it is always handled specially.*/#define NAV 128 /* number of bins */typedef Chunk* mbinptr;/* access macros */#define bin_at(i) ((mbinptr)((char*)&(av_[2*(i) + 2]) - 2*SIZE_SZ))#define next_bin(b) ((mbinptr)((char*)(b) + 2 * sizeof(mbinptr)))#define prev_bin(b) ((mbinptr)((char*)(b) - 2 * sizeof(mbinptr)))/* The first 2 bins are never indexed. The corresponding av_ cells are instead used for bookkeeping. This is not to save space, but to simplify indexing, maintain locality, and avoid some initialization tests.*/#define top (bin_at(0)->fd) /* The topmost chunk */#define last_remainder (bin_at(1)) /* remainder from last split *//* Because top initially points to its own bin with initial zero size, thus forcing extension on the first malloc request, we avoid having any special code in malloc to check whether it even exists yet. But we still need to in malloc_extend_top.*/#define initial_top ((mchunkptr)(bin_at(0)))/* Helper macro to initialize bins */#define IAV(i) bin_at(i), bin_at(i)static mbinptr av_[NAV * 2 + 2] = { 0, 0, IAV(0), IAV(1), IAV(2), IAV(3), IAV(4), IAV(5), IAV(6), IAV(7), IAV(8), IAV(9), IAV(10), IAV(11), IAV(12), IAV(13), IAV(14), IAV(15), IAV(16), IAV(17), IAV(18), IAV(19), IAV(20), IAV(21), IAV(22), IAV(23), IAV(24), IAV(25), IAV(26), IAV(27), IAV(28), IAV(29), IAV(30), IAV(31), IAV(32), IAV(33), IAV(34), IAV(35), IAV(36), IAV(37), IAV(38), IAV(39), IAV(40), IAV(41), IAV(42), IAV(43), IAV(44), IAV(45), IAV(46), IAV(47), IAV(48), IAV(49), IAV(50), IAV(51), IAV(52), IAV(53), IAV(54), IAV(55), IAV(56), IAV(57), IAV(58), IAV(59), IAV(60), IAV(61), IAV(62), IAV(63), IAV(64), IAV(65), IAV(66), IAV(67), IAV(68), IAV(69), IAV(70), IAV(71), IAV(72), IAV(73), IAV(74), IAV(75), IAV(76), IAV(77), IAV(78), IAV(79), IAV(80), IAV(81), IAV(82), IAV(83), IAV(84), IAV(85), IAV(86), IAV(87), IAV(88), IAV(89), IAV(90), IAV(91), IAV(92), IAV(93), IAV(94), IAV(95), IAV(96), IAV(97), IAV(98), IAV(99), IAV(100), IAV(101), IAV(102), IAV(103), IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109), IAV(110), IAV(111), IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), IAV(119), IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127)};/* field-extraction macros */#define first(b) ((b)->fd)#define last(b) ((b)->bk)/* Indexing into bins*/#define bin_index(sz) \(((((unsigned long)(sz)) >> 9) == 0) ? (((unsigned long)(sz)) >> 3): \ ((((unsigned long)(sz)) >> 9) <= 4) ? 56 + (((unsigned long)(sz)) >> 6): \ ((((unsigned long)(sz)) >> 9) <= 20) ? 91 + (((unsigned long)(sz)) >> 9): \ ((((unsigned long)(sz)) >> 9) <= 84) ? 110 + (((unsigned long)(sz)) >> 12): \ ((((unsigned long)(sz)) >> 9) <= 340) ? 119 + (((unsigned long)(sz)) >> 15): \ ((((unsigned long)(sz)) >> 9) <= 1364) ? 124 + (((unsigned long)(sz)) >> 18): \ 126)/* bins for chunks < 512 are all spaced 8 bytes apart, and hold identically sized chunks. This is exploited in malloc.*/#define MAX_SMALLBIN 63#define MAX_SMALLBIN_SIZE 512#define SMALLBIN_WIDTH 8#define smallbin_index(sz) (((unsigned long)(sz)) >> 3)/* Requests are `small' if both the corresponding and the next bin are small*/#define is_small_request(nb) (nb < MAX_SMALLBIN_SIZE - SMALLBIN_WIDTH)/* To help compensate for the large number of bins, a one-level index structure is used for bin-by-bin searching. `binblocks' is a one-word bitvector recording whether groups of BINBLOCKWIDTH bins have any (possibly) non-empty bins, so they can be skipped over all at once during during traversals. The bits are NOT always cleared as soon as all bins in a block are empty, but instead only when all are noticed to be empty during traversal in malloc.*/#define BINBLOCKWIDTH 4 /* bins per block */#define binblocks (bin_at(0)->size) /* bitvector of nonempty blocks *//* bin<->block macros */#define idx2binblock(ix) ((unsigned)1 << (ix / BINBLOCKWIDTH))#define mark_binblock(ii) (binblocks |= idx2binblock(ii))#define clear_binblock(ii) (binblocks &= ~(idx2binblock(ii)))/* Other static bookkeeping data *//* variables holding tunable values */static unsigned long trim_threshold = DEFAULT_TRIM_THRESHOLD;static unsigned long top_pad = DEFAULT_TOP_PAD;static unsigned int n_mmaps_max = DEFAULT_MMAP_MAX;static unsigned long mmap_threshold = DEFAULT_MMAP_THRESHOLD;#ifdef DEBUG2static int scanheap = 1;#endif/* The first value returned from sbrk */static char* sbrk_base = (char*)(-1);/* The maximum memory obtained from system via sbrk */static unsigned long max_sbrked_mem = 0;/* The maximum via either sbrk or mmap */static unsigned long max_total_mem = 0;/* internal working copy of mallinfo */static struct mallinfo current_mallinfo = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };/* The total memory obtained from system via sbrk */#define sbrked_mem (current_mallinfo.arena)/* Tracking mmaps */static unsigned int n_mmaps = 0;static unsigned long mmapped_mem = 0;#if HAVE_MMAPstatic unsigned int max_n_mmaps = 0;static unsigned long max_mmapped_mem = 0;#endif/* Debugging support*/#if DEBUG#ifndef DEBUG2# define unless(cond, err, p) assert(cond)#else# define unless(cond, err, p) do { if (!(cond)) malloc_err(err, p); } while (0)/* * When debug_file is non-null, it and debug_line respectively contain the * file and line number of the current invocation of malloc(), calloc(), * realloc(), or free(). */static const char *debug_file = NULL;static int debug_line;/* * Avoid dereferencing invalid chunk.file pointers by tracking the range of * valid ones. Could add an "unallocated" flag to init_freed_chunk() for * more protection, but that's probably not necessary. */static const char *debug_file_min = (char *)~0;static const char *debug_file_max = NULL;static char *itos(int n){#define NDIGITS (sizeof(int) * 3) static char s[NDIGITS + 1]; int i = NDIGITS; do { s[--i] = '0' + n % 10; n /= 10; } while (n); return s + i;#undef NDIGITS}static int recurs = 0;static void errprint(const char *file, int line, const char *err){ if (recurs++) { recurs--; return; } if (file) { write(2, file, strlen(file)); if (line) { write(2, ":", 1); write(2, itos(line), strlen(itos(line))); } write(2, ": ", 2); } write(2, err, strlen(err)); write(2, "\n", 1); recurs--;}static void malloc_err(const char *err, mchunkptr p){ /* * Display ERR on stderr, accompanying it with the caller's file and line * number if available. If P is non-null, also attempt to display the file * and line number at which P was most recently [re]allocated. * * This function's name begins with "malloc_" to make setting debugger * breakpoints here more convenient. */ errprint(debug_file, debug_line, err);# ifndef DEBUG3 p = 0; /* avoid "unused param" warning */# else if (p && p->file && /* avoid invalid pointers */ debug_file_min && p->file >= debug_file_min && p->file <= debug_file_max && /* try to avoid garbage file names */ isprint(*p->file)) errprint(p->file, p->line, "in block allocated here");# endif}#undef malloc#undef free#undef realloc#undef memalign#undef valloc#undef pvalloc#undef calloc#undef cfree#undef malloc_trim#undef malloc_usable_size#undef malloc_stats#undef mallopt#undef mallinfostatic void malloc_update_mallinfo(void);/* * Define front-end functions for all user-visible entry points that may * trigger error(). */#define skel(retdecl, retassign, call, retstmt) \ retdecl \ debug_file = file; \ debug_line = line; \ if (debug_file < debug_file_min) \ debug_file_min = debug_file; \ if (debug_file > debug_file_max) \ debug_file_max = debug_file; \ if (scanheap) \ malloc_update_mallinfo(); \ retassign call; \ if (scanheap) \ malloc_update_mallinfo(); \ debug_file = NULL; \ retstmt/* * The final letter of the names of the following macros is either r or v, * indicating that the macro handles functions with or without a return value, * respectively. */# define skelr(rettype, call) \ skel(rettype ret;, ret = , call, return ret)/* * AIX's xlc compiler doesn't like empty macro args, so specify useless but * compilable retdecl, retassign, and retstmt args: */#define skelv(call) \ skel(line += 0;, if (1), call, return)#define dbgargs const char *file, int line/* * Front-end function definitions: */Void_t* malloc_dbg(size_t bytes, dbgargs) { skelr(Void_t*, malloc(bytes));}void free_dbg(Void_t *mem, dbgargs) { skelv(free(mem));}Void_t* realloc_dbg(Void_t *oldmem, size_t bytes, dbgargs) { skelr(Void_t*, realloc(oldmem, bytes));}Void_t* memalign_dbg(size_t alignment, size_t bytes, dbgargs) { skelr(Void_t*, memalign(alignment, bytes));}Void_t* valloc_dbg(size_t bytes, dbgargs) { skelr(Void_t*, valloc(bytes));}Void_t* pvalloc_dbg(size_t bytes, dbgargs) { skelr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -