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
- }
}
}
#if REALLOC_ZERO_BYTES_FREES
if (bytes == 0) {
- _int_free(av, oldmem);
+ if (oldmem != 0)
+ _int_free(av, oldmem);
return 0;
}
#endif