diff options
Diffstat (limited to 'malloc/malloc.c')
-rw-r--r-- | malloc/malloc.c | 308 |
1 files changed, 153 insertions, 155 deletions
diff --git a/malloc/malloc.c b/malloc/malloc.c index 3f4fd77807..d2112b159a 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -4196,191 +4196,188 @@ _int_free(mstate av, Void_t* mem) mchunkptr fwd; /* misc temp for linking */ - /* free(0) has no effect */ - if (mem != 0) { - const char *errstr = NULL; + const char *errstr = NULL; - p = mem2chunk(mem); - size = chunksize(p); + p = mem2chunk(mem); + size = chunksize(p); - /* Little security check which won't hurt performance: the - allocator never wrapps around at the end of the address space. - Therefore we can exclude some size values which might appear - here by accident or by "design" from some intruder. */ - if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)) - { - errstr = "free(): invalid pointer"; - errout: - malloc_printerr (check_action, errstr, mem); - return; - } + /* Little security check which won't hurt performance: the + allocator never wrapps around at the end of the address space. + Therefore we can exclude some size values which might appear + here by accident or by "design" from some intruder. */ + if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)) + { + errstr = "free(): invalid pointer"; + errout: + malloc_printerr (check_action, errstr, mem); + return; + } - check_inuse_chunk(av, p); + check_inuse_chunk(av, p); - /* - If eligible, place chunk on a fastbin so it can be found - and used quickly in malloc. - */ + /* + If eligible, place chunk on a fastbin so it can be found + and used quickly in malloc. + */ - if ((unsigned long)(size) <= (unsigned long)(av->max_fast) + if ((unsigned long)(size) <= (unsigned long)(av->max_fast) #if TRIM_FASTBINS - /* - If TRIM_FASTBINS set, don't place chunks - bordering top into fastbins - */ - && (chunk_at_offset(p, size) != av->top) -#endif - ) { - - set_fastchunks(av); - fb = &(av->fastbins[fastbin_index(size)]); - /* Another simple check: make sure the top of the bin is not the - record we are going to add (i.e., double free). */ - if (__builtin_expect (*fb == p, 0)) - { - errstr = "double free or corruption (fasttop)"; - goto errout; - } - p->fd = *fb; - *fb = p; - } - - /* - Consolidate other non-mmapped chunks as they arrive. - */ + /* + If TRIM_FASTBINS set, don't place chunks + bordering top into fastbins + */ + && (chunk_at_offset(p, size) != av->top) +#endif + ) { - else if (!chunk_is_mmapped(p)) { - nextchunk = chunk_at_offset(p, size); + set_fastchunks(av); + fb = &(av->fastbins[fastbin_index(size)]); + /* Another simple check: make sure the top of the bin is not the + record we are going to add (i.e., double free). */ + if (__builtin_expect (*fb == p, 0)) + { + errstr = "double free or corruption (fasttop)"; + goto errout; + } + p->fd = *fb; + *fb = p; + } - /* Lightweight tests: check whether the block is already the - top block. */ - if (__builtin_expect (p == av->top, 0)) - { - errstr = "double free or corruption (top)"; - goto errout; - } - /* Or whether the next chunk is beyond the boundaries of the arena. */ - if (__builtin_expect (contiguous (av) - && (char *) nextchunk - >= ((char *) av->top + chunksize(av->top)), 0)) - { - errstr = "double free or corruption (out)"; - goto errout; - } - /* Or whether the block is actually not marked used. */ - if (__builtin_expect (!prev_inuse(nextchunk), 0)) - { - errstr = "double free or corruption (!prev)"; - goto errout; - } + /* + Consolidate other non-mmapped chunks as they arrive. + */ - nextsize = chunksize(nextchunk); - assert(nextsize > 0); + else if (!chunk_is_mmapped(p)) { + nextchunk = chunk_at_offset(p, size); - /* consolidate backward */ - if (!prev_inuse(p)) { - prevsize = p->prev_size; - size += prevsize; - p = chunk_at_offset(p, -((long) prevsize)); - unlink(p, bck, fwd); + /* Lightweight tests: check whether the block is already the + top block. */ + if (__builtin_expect (p == av->top, 0)) + { + errstr = "double free or corruption (top)"; + goto errout; + } + /* Or whether the next chunk is beyond the boundaries of the arena. */ + if (__builtin_expect (contiguous (av) + && (char *) nextchunk + >= ((char *) av->top + chunksize(av->top)), 0)) + { + errstr = "double free or corruption (out)"; + goto errout; + } + /* Or whether the block is actually not marked used. */ + if (__builtin_expect (!prev_inuse(nextchunk), 0)) + { + errstr = "double free or corruption (!prev)"; + goto errout; } - if (nextchunk != av->top) { - /* get and clear inuse bit */ - nextinuse = inuse_bit_at_offset(nextchunk, nextsize); - - /* consolidate forward */ - if (!nextinuse) { - unlink(nextchunk, bck, fwd); - size += nextsize; - } else - clear_inuse_bit_at_offset(nextchunk, 0); - - /* - Place the chunk in unsorted chunk list. Chunks are - not placed into regular bins until after they have - been given one chance to be used in malloc. - */ + nextsize = chunksize(nextchunk); + assert(nextsize > 0); - bck = unsorted_chunks(av); - fwd = bck->fd; - p->bk = bck; - p->fd = fwd; - bck->fd = p; - fwd->bk = p; + /* consolidate backward */ + if (!prev_inuse(p)) { + prevsize = p->prev_size; + size += prevsize; + p = chunk_at_offset(p, -((long) prevsize)); + unlink(p, bck, fwd); + } - set_head(p, size | PREV_INUSE); - set_foot(p, size); + if (nextchunk != av->top) { + /* get and clear inuse bit */ + nextinuse = inuse_bit_at_offset(nextchunk, nextsize); - check_free_chunk(av, p); - } + /* consolidate forward */ + if (!nextinuse) { + unlink(nextchunk, bck, fwd); + size += nextsize; + } else + clear_inuse_bit_at_offset(nextchunk, 0); /* - If the chunk borders the current high end of memory, - consolidate into top + Place the chunk in unsorted chunk list. Chunks are + not placed into regular bins until after they have + been given one chance to be used in malloc. */ - else { - size += nextsize; - set_head(p, size | PREV_INUSE); - av->top = p; - check_chunk(av, p); - } + bck = unsorted_chunks(av); + fwd = bck->fd; + p->bk = bck; + p->fd = fwd; + bck->fd = p; + fwd->bk = p; - /* - If freeing a large space, consolidate possibly-surrounding - chunks. Then, if the total unused topmost memory exceeds trim - threshold, ask malloc_trim to reduce top. - - Unless max_fast is 0, we don't know if there are fastbins - bordering top, so we cannot tell for sure whether threshold - has been reached unless fastbins are consolidated. But we - don't want to consolidate on each free. As a compromise, - consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD - is reached. - */ + set_head(p, size | PREV_INUSE); + set_foot(p, size); + + check_free_chunk(av, p); + } + + /* + If the chunk borders the current high end of memory, + consolidate into top + */ - if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { - if (have_fastchunks(av)) - malloc_consolidate(av); + else { + size += nextsize; + set_head(p, size | PREV_INUSE); + av->top = p; + check_chunk(av, p); + } + + /* + If freeing a large space, consolidate possibly-surrounding + chunks. Then, if the total unused topmost memory exceeds trim + threshold, ask malloc_trim to reduce top. + + Unless max_fast is 0, we don't know if there are fastbins + bordering top, so we cannot tell for sure whether threshold + has been reached unless fastbins are consolidated. But we + don't want to consolidate on each free. As a compromise, + consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD + is reached. + */ - if (av == &main_arena) { + if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { + if (have_fastchunks(av)) + malloc_consolidate(av); + + if (av == &main_arena) { #ifndef MORECORE_CANNOT_TRIM - if ((unsigned long)(chunksize(av->top)) >= - (unsigned long)(mp_.trim_threshold)) - sYSTRIm(mp_.top_pad, av); + if ((unsigned long)(chunksize(av->top)) >= + (unsigned long)(mp_.trim_threshold)) + sYSTRIm(mp_.top_pad, av); #endif - } else { - /* Always try heap_trim(), even if the top chunk is not - large, because the corresponding heap might go away. */ - heap_info *heap = heap_for_ptr(top(av)); + } else { + /* Always try heap_trim(), even if the top chunk is not + large, because the corresponding heap might go away. */ + heap_info *heap = heap_for_ptr(top(av)); - assert(heap->ar_ptr == av); - heap_trim(heap, mp_.top_pad); - } + assert(heap->ar_ptr == av); + heap_trim(heap, mp_.top_pad); } - } - /* - If the chunk was allocated via mmap, release via munmap(). Note - that if HAVE_MMAP is false but chunk_is_mmapped is true, then - user must have overwritten memory. There's nothing we can do to - catch this error unless MALLOC_DEBUG is set, in which case - check_inuse_chunk (above) will have triggered error. - */ - else { + } + /* + If the chunk was allocated via mmap, release via munmap(). Note + that if HAVE_MMAP is false but chunk_is_mmapped is true, then + user must have overwritten memory. There's nothing we can do to + catch this error unless MALLOC_DEBUG is set, in which case + check_inuse_chunk (above) will have triggered error. + */ + + else { #if HAVE_MMAP - int ret; - INTERNAL_SIZE_T offset = p->prev_size; - mp_.n_mmaps--; - mp_.mmapped_mem -= (size + offset); - ret = munmap((char*)p - offset, size + offset); - /* munmap returns non-zero on failure */ - assert(ret == 0); + int ret; + INTERNAL_SIZE_T offset = p->prev_size; + mp_.n_mmaps--; + mp_.mmapped_mem -= (size + offset); + ret = munmap((char*)p - offset, size + offset); + /* munmap returns non-zero on failure */ + assert(ret == 0); #endif - } } } @@ -4528,7 +4525,8 @@ _int_realloc(mstate av, Void_t* oldmem, size_t bytes) #if REALLOC_ZERO_BYTES_FREES if (bytes == 0) { - _int_free(av, oldmem); + if (oldmem != 0) + _int_free(av, oldmem); return 0; } #endif |