📄 malloc.c
字号:
return; /* Mark the block appropriately and add it to the free list. */#if ALLOC_CHECK _add_free_called = 1; /* because _alloc_check() needs to know */#endif /* ALLOC_CHECK */ p = (BLOCK *)ptr; size -= OVERHEAD; /* for empty marker at end */ p->losize = 0 | MARKBIT; /* predecessor size 0 */ setsizes(p, size); /* size of added block */ succ(p)->size = 0 | MARKBIT; /* successor size 0 */ add(p); /* add to free list */}#if ALLOC_CHECK/* * Sanity check the memory arena and the free list. * Dump the memory arena if dflag, * dump the free list if fflag. */voidFN_ALLOC_CHECK(int dflag, int fflag){ BLOCK *p; size_t n, nbytes, nblocks, nblocksfree, nbytesfree, largest; char *s; /* Check the memory arena. */ if ((p = arena_start) != NULL) { if (dflag) printf("Memory arena:\n"); nbytes = nblocks = nblocksfree = nbytesfree = 0; do { n = p->size & ~MARKBIT; ++nblocks; nbytes += n; if (is_free(p)) { s = "free"; ++nblocksfree; nbytesfree += n; } else s = "used"; if (dflag) printf("\t%X\t%d\t%s\n", p, n, s); check(p->size, succ(p)->losize); p = succ(p); } while (p != arena_end); ++nblocks; /* for arena_end block */ nbytes += OVERHEAD; /* for arena_end block */ check(nbytes, (char *)arena_end - (char *)arena_start + OVERHEAD);#if ALLOC_STATS check(n_blocks, nblocks); check(n_bytes, nbytes); if (_add_free_called == 0) { check(n_blocks_free, nblocksfree); check(n_bytes_free, nbytesfree); }#endif /* ALLOC_STATS */ if (dflag) putchar('\n'); } /* Check the free list. */ if (fflag) printf("Free list:\n"); largest = nbytes = nblocks = 0; p = rover; check(p->prev->next, p); do { if (fflag) printf("\t%X\t%d\n", p, p->size); ++nblocks; nbytes += p->size; if (p->size > largest) largest = p->size; check(p->next->prev, p); p = p->next; } while (p != rover); --nblocks; /* do not count freelist0 */#if ALLOC_STATS if (_add_free_called == 0) { check(nblocks, n_blocks_free); check(nbytes, n_bytes_free); }#endif /* ALLOC_STATS */ if (fflag) putchar('\n');}#endif /* ALLOC_CHECK */#if ALLOC_STATS/* Report statistics. */voidFN_ALLOC_STATS(void){ printf("_alloc_stats():\n"); printf("sbrk():\t\t%d calls (%d failed)\n", n_calls_sbrk, n_calls_sbrk_failed); if (n_calls_calloc != 0) printf("calloc():\t%d calls\n", n_calls_calloc); if (n_calls_free != 0) printf("free():\t\t%d calls\n", n_calls_free); if (n_calls_malloc != 0) printf("malloc():\t%d calls\n", n_calls_malloc); if (n_calls_realloc != 0) printf("realloc():\t%d calls\n", n_calls_realloc); printf("\tTotal\tUsed\tFree\tUnallocated\n"); printf("Blocks:\t%d\t%d\t%d\t%d\n", n_blocks, n_blocks - n_blocks_free - n_blocks_unalloc, n_blocks_free, n_blocks_unalloc); printf("Bytes:\t%d\t%d\t%d\t%d\n\n", n_bytes, n_bytes - n_bytes_free - n_bytes_unalloc, n_bytes_free, n_bytes_unalloc);}#endif /* ALLOC_STATS *//* Conditionalized out: cf. calloc.c. *//* Allocate and clear memory. */void *FN_CALLOC(size_t nmemb, size_t size){ void *FN_MALLOC(size_t size); void *s; alloc_stat(++n_calls_calloc); size *= nmemb; if ((s = FN_MALLOC(size)) == NULL) return NULL; memset(s, 0, size); return s;}/* * Free allocated memory. * Avoid fragmentation of the memory arena by joining all adjacent freed blocks. */voidFN_FREE(void *ptr){ BLOCK *p, *q; size_t n; alloc_stat(++n_calls_free); if (ptr == NULL) return; /* ANSI says so */ /* Make sure the block is currently allocated. */ p = blockp(ptr); if (is_free(p)) { /* block is not allocated */#if ALLOC_ERRORS fprintf(stderr, "free(0x%X): unallocated block\n", (uint)ptr); abort(); /* print message and die */#else /* !ALLOC_ERRORS */ return; /* ignore */#endif /* !ALLOC_ERRORS */ } EXCL_START(); clearmarks(p); /* mark this block as free */ /* Coalese with predecessor block if free. */ if (is_predfree(p)) { /* Coalese this block with free predecessor block. */ n = p->size; alloc_stat(--n_blocks); alloc_stat(n_bytes_free += n); p = pred(p); setsizes(p, p->size + n); delete(p); /* delete p from the free list */ /* (it gets put back again below...) */ } /* Coalese with successor block if free. */ q = succ(p); if (is_free(q)) { /* Coalese p with successor free block q. */ alloc_stat(--n_blocks); setsizes(p, p->size + q->size); if (rover == q) rover = p; delete(q); /* delete q from the free list */ } add(p); /* add p to freelist */ EXCL_END();}/* Allocate memory. */void *FN_MALLOC(size_t size){ BLOCK *p, *q; size_t m, n; alloc_stat(++n_calls_malloc); if (size == (size_t)0) return NULL; /* implementation-defined behavior */ /* Search the freelist for a big enough block. */ EXCL_START(); n = roundup(needed(size), ALIGNMENT); /* needed memory block size */ p = rover; do { if (p->size >= n) break; /* block p is large enough */ p = p->next; } while (p != rover); if (p->size < n) { EXCL_END(); return NULL; /* allocation failed */ } /* Found or allocated a suitable free block p. */ rover = p->next; m = p->size; if (m - n >= MINBLOCK) { /* * Split block p into free and used parts. * Rather than leaving the bottom block free * and just leaving it on the free list, * this leaves the top part free. This requires an * extra add() and delete(), but leaving the top part free * helps avoid fragmentation when grow_arena() adds memory, * because the top of the previous arena is often free. */ alloc_stat(++n_blocks); setsizes(p, n); q = succ(p); setsizes(q, m - n); alloc_stat(n_bytes_free -= m - n); add(q); } delete(p); /* delete p from free list */ setmarks(p); /* mark p as used */ EXCL_END(); return (void *)memory(p);}/* Reallocate memory. */void *FN_REALLOC(void *ptr, size_t size){ BLOCK *p; size_t old, new; void *vp; alloc_stat(++n_calls_realloc); if (ptr == NULL) return FN_MALLOC(size); /* ANSI says so */ if (size == (size_t)0) { FN_FREE(ptr); /* ANSI says so */ return NULL; /* implementation-defined */ } /* Make sure the block is currently allocated. */ p = blockp(ptr); if (is_free(p)) { /* block is not allocated */#if ALLOC_ERRORS fprintf(stderr, "realloc(0x%X, %d): unallocated block\n", (uint)ptr, size); abort(); /* print message and die */#else /* !ALLOC_ERRORS */ return NULL; /* ignore */#endif /* !ALLOC_ERRORS */ } EXCL_START(); old = (p->size & ~MARKBIT); new = roundup(needed(size), ALIGNMENT); if (new <= old) { /* Shrink the block: either return unchanged or split it. */ if (old - new < MINBLOCK) { EXCL_END(); return ptr; /* return block unchanged */ } /* Shrink the block by splitting it. */ alloc_stat(++n_blocks); setsizes(p, new); setmarks(p); p = succ(p); setsizes(p, old - new); add(p); EXCL_END(); return ptr; } else { /* Grow the block. */ /* N.B. Could check if enough space in start of next block... */ EXCL_END(); if ((vp = FN_MALLOC(size)) == NULL) return NULL; memcpy(vp, ptr, old - OVERHEAD); free(ptr); return vp; }}/* end of malloc.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -