Try to free all pointers in the given array. Note: this could be made faster, by delaying consolidation, at the price of disabling some user integrity checks, We still optimize some consolidations by combining adjacent chunks before freeing, which will occur often if allocated with ialloc or the array is sorted. */
| 5090 | with ialloc or the array is sorted. |
| 5091 | */ |
| 5092 | static size_t internal_bulk_free(mstate m, void* array[], size_t nelem) { |
| 5093 | size_t unfreed = 0; |
| 5094 | if (!PREACTION(m)) { |
| 5095 | void** a; |
| 5096 | void** fence = &(array[nelem]); |
| 5097 | for (a = array; a != fence; ++a) { |
| 5098 | void* mem = *a; |
| 5099 | if (mem != 0) { |
| 5100 | mchunkptr p = mem2chunk(mem); |
| 5101 | size_t psize = chunksize(p); |
| 5102 | #if FOOTERS |
| 5103 | if (get_mstate_for(p) != m) { |
| 5104 | ++unfreed; |
| 5105 | continue; |
| 5106 | } |
| 5107 | #endif |
| 5108 | check_inuse_chunk(m, p); |
| 5109 | *a = 0; |
| 5110 | if (RTCHECK(ok_address(m, p) && ok_inuse(p))) { |
| 5111 | void ** b = a + 1; /* try to merge with next chunk */ |
| 5112 | mchunkptr next = next_chunk(p); |
| 5113 | if (b != fence && *b == chunk2mem(next)) { |
| 5114 | size_t newsize = chunksize(next) + psize; |
| 5115 | set_inuse(m, p, newsize); |
| 5116 | *b = chunk2mem(p); |
| 5117 | } |
| 5118 | else |
| 5119 | dispose_chunk(m, p, psize); |
| 5120 | } |
| 5121 | else { |
| 5122 | CORRUPTION_ERROR_ACTION(m); |
| 5123 | break; |
| 5124 | } |
| 5125 | } |
| 5126 | } |
| 5127 | if (should_trim(m, m->topsize)) |
| 5128 | sys_trim(m, 0); |
| 5129 | POSTACTION(m); |
| 5130 | } |
| 5131 | return unfreed; |
| 5132 | } |
| 5133 | |
| 5134 | /* Traversal */ |
| 5135 | #if MALLOC_INSPECT_ALL |
no test coverage detected