| 677 | } |
| 678 | |
| 679 | void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) mi_attr_noexcept { |
| 680 | // if p == NULL then behave as malloc. |
| 681 | // else if size == 0 then reallocate to a zero-sized block (and don't return NULL, just as mi_malloc(0)). |
| 682 | // (this means that returning NULL always indicates an error, and `p` will not have been freed in that case.) |
| 683 | const size_t size = _mi_usable_size(p,"mi_realloc"); // also works if p == NULL (with size 0) |
| 684 | if mi_unlikely(newsize <= size && newsize >= (size / 2) && newsize > 0) { // note: newsize must be > 0 or otherwise we return NULL for realloc(NULL,0) |
| 685 | // todo: adjust potential padding to reflect the new size? |
| 686 | mi_track_free_size(p, size); |
| 687 | mi_track_malloc(p,newsize,true); |
| 688 | return p; // reallocation still fits and not more than 50% waste |
| 689 | } |
| 690 | void* newp = mi_heap_malloc(heap,newsize); |
| 691 | if mi_likely(newp != NULL) { |
| 692 | if (zero && newsize > size) { |
| 693 | // also set last word in the previous allocation to zero to ensure any padding is zero-initialized |
| 694 | const size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0); |
| 695 | memset((uint8_t*)newp + start, 0, newsize - start); |
| 696 | } |
| 697 | if mi_likely(p != NULL) { |
| 698 | if mi_likely(_mi_is_aligned(p, sizeof(uintptr_t))) { // a client may pass in an arbitrary pointer `p`.. |
| 699 | const size_t copysize = (newsize > size ? size : newsize); |
| 700 | mi_track_mem_defined(p,copysize); // _mi_useable_size may be too large for byte precise memory tracking.. |
| 701 | _mi_memcpy_aligned(newp, p, copysize); |
| 702 | } |
| 703 | mi_free(p); // only free the original pointer if successful |
| 704 | } |
| 705 | } |
| 706 | return newp; |
| 707 | } |
no test coverage detected