diff --git a/include/mimalloc-internal.h b/include/mimalloc-internal.h index 3591871a..cfdcf858 100644 --- a/include/mimalloc-internal.h +++ b/include/mimalloc-internal.h @@ -22,18 +22,14 @@ terms of the MIT license. A copy of the license can be found in the file #define mi_decl_noinline __declspec(noinline) #define mi_decl_thread __declspec(thread) #define mi_decl_cache_align __declspec(align(MI_CACHE_LINE)) -#include -#define mi_return_address() _ReturnAddress() #elif (defined(__GNUC__) && (__GNUC__>=3)) // includes clang and icc #define mi_decl_noinline __attribute__((noinline)) #define mi_decl_thread __thread #define mi_decl_cache_align __attribute__((aligned(MI_CACHE_LINE))) -#define mi_return_address() __builtin_return_address(0) #else #define mi_decl_noinline #define mi_decl_thread __thread // hope for the best :-) #define mi_decl_cache_align -#define mi_return_address() #endif @@ -135,9 +131,6 @@ void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size); mi_decl_allocator void* _mi_heapx_malloc(mi_heap_t* heap, size_t size MI_SOURCE_PARAM) mi_attr_noexcept; mi_decl_allocator void* _mi_heapx_malloc_zero(mi_heap_t* heap, size_t size, bool zero MI_SOURCE_PARAM); mi_decl_allocator void* _mi_heapx_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero MI_SOURCE_PARAM); -mi_decl_allocator void* _mi_heapx_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment MI_SOURCE_PARAM) mi_attr_noexcept; -mi_decl_allocator void* _mi_heapx_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size MI_SOURCE_PARAM) mi_attr_noexcept; -mi_decl_allocator char* _mi_heapx_strdup(mi_heap_t* heap, const char* s MI_SOURCE_PARAM) mi_attr_noexcept; #if MI_DEBUG>1 bool _mi_page_is_valid(mi_page_t* page); diff --git a/include/mimalloc-new-delete.h b/include/mimalloc-new-delete.h index fded0c04..0c6b1fff 100644 --- a/include/mimalloc-new-delete.h +++ b/include/mimalloc-new-delete.h @@ -25,11 +25,11 @@ terms of the MIT license. A copy of the license can be found in the file void operator delete(void* p) noexcept { mi_free(p); }; void operator delete[](void* p) noexcept { mi_free(p); }; - void* operator new(std::size_t n) noexcept(false) { return mi_new(n); } - void* operator new[](std::size_t n) noexcept(false) { return mi_new(n); } + void* operator new(std::size_t n) noexcept(false) { return mi_source_new(n MI_SOURCE_RET()); } + void* operator new[](std::size_t n) noexcept(false) { return mi_source_new(n MI_SOURCE_RET()); } - void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); } - void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); } + void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_source_new_nothrow(n MI_SOURCE_RET()); } + void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_source_new_nothrow(n MI_SOURCE_RET()); } #if (__cplusplus >= 201402L || _MSC_VER >= 1916) void operator delete (void* p, std::size_t n) noexcept { mi_free_size(p,n); }; @@ -42,10 +42,10 @@ terms of the MIT license. A copy of the license can be found in the file void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast(al)); }; - void* operator new( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } - void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast(al)); } - void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } - void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast(al)); } + void* operator new( std::size_t n, std::align_val_t al) noexcept(false) { return mi_source_new_aligned(n, static_cast(al) MI_SOURCE_RET()); } + void* operator new[]( std::size_t n, std::align_val_t al) noexcept(false) { return mi_source_new_aligned(n, static_cast(al) MI_SOURCE_RET()); } + void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_source_new_aligned_nothrow(n, static_cast(al) MI_SOURCE_RET()); } + void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_source_new_aligned_nothrow(n, static_cast(al) MI_SOURCE_RET()); } #endif #endif diff --git a/include/mimalloc-override.h b/include/mimalloc-override.h index 201fb8b4..e5bfb5c5 100644 --- a/include/mimalloc-override.h +++ b/include/mimalloc-override.h @@ -18,22 +18,22 @@ not accidentally mix pointers from different allocators). #include // Standard C allocation -#define malloc(n) mi_malloc(n) -#define calloc(n,c) mi_calloc(n,c) -#define realloc(p,n) mi_realloc(p,n) +#define malloc(n) mi_source_malloc(n MI_SOURCE_LOC()) +#define calloc(n,c) mi_source_calloc(n,c MI_SOURCE_LOC()) +#define realloc(p,n) mi_source_realloc(p,n MI_SOURCE_LOC()) #define free(p) mi_free(p) -#define strdup(s) mi_strdup(s) -#define strndup(s) mi_strndup(s) -#define realpath(f,n) mi_realpath(f,n) +#define strdup(s) mi_source_strdup(s MI_SOURCE_LOC()) +#define strndup(s) mi_source_strndup(s MI_SOURCE_LOC()) +#define realpath(f,n) mi_source_realpath(f,n MI_SOURCE_LOC()) // Microsoft extensions #define _expand(p,n) mi_expand(p,n) #define _msize(p) mi_usable_size(p) #define _recalloc(p,n,c) mi_recalloc(p,n,c) -#define _strdup(s) mi_strdup(s) -#define _strndup(s) mi_strndup(s) +#define _strdup(s) mi_source_strdup(s MI_SOURCE_LOC()) +#define _strndup(s) mi_source_strndup(s MI_SOURCE_LOC()) #define _wcsdup(s) (wchar_t*)mi_wcsdup((const unsigned short*)(s)) #define _mbsdup(s) mi_mbsdup(s) #define _dupenv_s(b,n,v) mi_dupenv_s(b,n,v) @@ -54,7 +54,7 @@ not accidentally mix pointers from different allocators). #define _posix_memalign(p,a,n) mi_posix_memalign(p,a,n) // Microsoft aligned variants -#define _aligned_malloc(n,a) mi_malloc_aligned(n,a) +#define _aligned_malloc(n,a) mi_source_malloc_aligned(n,a MI_SOURCE_LOC()) #define _aligned_realloc(p,n,a) mi_realloc_aligned(p,n,a) #define _aligned_recalloc(p,s,n,a) mi_aligned_recalloc(p,s,n,a) #define _aligned_msize(p,a,o) mi_usable_size(p) diff --git a/include/mimalloc-types.h b/include/mimalloc-types.h index e04705b2..7cf0786e 100644 --- a/include/mimalloc-types.h +++ b/include/mimalloc-types.h @@ -274,10 +274,6 @@ typedef struct mi_segment_s { // of the blocks to check for buffer overflows. // ------------------------------------------------------ #if defined(MI_PADDING) -// compressed location: -// lsb=1: bit 63-32: relative file name char* (to `mi_fname_base`), bit 31-1: line number -// lsb=0: bit 63-01: return address -typedef int64_t mi_source_t; typedef struct mi_padding_s { uint32_t canary; // encoded block value to check validity of the padding (in case of heap block overflow) uint32_t delta; // padding bytes before the block. (mi_usable_size(p) - delta == exact allocated bytes) @@ -285,15 +281,9 @@ typedef struct mi_padding_s { } mi_padding_t; #define MI_PADDING_SIZE (sizeof(mi_padding_t)) #define MI_PADDING_WSIZE ((MI_PADDING_SIZE + MI_INTPTR_SIZE - 1) / MI_INTPTR_SIZE) -#define MI_SOURCE_PARAM , mi_source_t source -#define MI_SOURCE_ARG , source -#define MI_SOURCE_RET , ((intptr_t)mi_return_address() << (intptr_t)1) #else #define MI_PADDING_SIZE 0 #define MI_PADDING_WSIZE 0 -#define MI_SOURCE_PARAM -#define MI_SOURCE_ARG -#define MI_SOURCE_RET #endif // ------------------------------------------------------ diff --git a/include/mimalloc.h b/include/mimalloc.h index 552a8b2b..df730e37 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -360,6 +360,58 @@ mi_decl_nodiscard mi_decl_export void* mi_new_n(size_t count, size_t size) mi_at mi_decl_nodiscard mi_decl_export void* mi_new_realloc(void* p, size_t newsize) mi_attr_malloc mi_attr_alloc_size(2); mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount, size_t size) mi_attr_malloc mi_attr_alloc_size2(2, 3); + +// --------------------------------------------------------------------------------------------- +// Experimental: Debugging API that tracks the source location of an allocation +// --------------------------------------------------------------------------------------------- + +typedef struct mi_source_s { + long long src; // packed encoding of the source location +} mi_source_t; + +mi_decl_export mi_source_t mi_source_ret(void* return_address); +mi_decl_export mi_source_t mi_source_loc(const char* fname, int lineno); +mi_decl_export void* mi_source_unpack(mi_source_t source, const char** fname, int* lineno); + +#ifdef NDEBUG +#define MI_SOURCE_PARAM +#define MI_SOURCE_ARG +#define MI_SOURCE_RET() +#define MI_SOURCE_LOC() +#else +#ifdef _MSC_VER +#include +#define mi_return_address() _ReturnAddress() +#elif (defined(__GNUC__) && (__GNUC__>=3)) // includes clang and icc +#define mi_return_address() __builtin_return_address(0) +#else +#define mi_return_address() NULL +#endif +#define MI_SOURCE_PARAM , mi_source_t __mi_source +#define MI_SOURCE_ARG , __mi_source +#define MI_SOURCE_RET() , mi_source_ret(mi_return_address()) +#define MI_SOURCE_LOC() , mi_source_loc(__FILE__,__LINE__) +#endif + +mi_decl_nodiscard mi_decl_export mi_decl_allocator void* mi_source_malloc(size_t size MI_SOURCE_PARAM) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export mi_decl_allocator void* mi_source_calloc(size_t count, size_t size MI_SOURCE_PARAM) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1, 2); +mi_decl_nodiscard mi_decl_export mi_decl_allocator void* mi_source_realloc(void* p, size_t newsize MI_SOURCE_PARAM) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(2); +mi_decl_nodiscard mi_decl_export mi_decl_allocator void* mi_source_malloc_aligned(size_t size, size_t alignment MI_SOURCE_PARAM) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export mi_decl_allocator void* mi_source_reallocn(void* p, size_t count, size_t size MI_SOURCE_PARAM) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(2, 3); +mi_decl_nodiscard mi_decl_export char* mi_source_strdup(const char* s MI_SOURCE_PARAM) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export char* mi_source_strndup(const char* s, size_t n MI_SOURCE_PARAM) mi_attr_noexcept; +mi_decl_nodiscard mi_decl_export char* mi_source_realpath(const char* fname, char* resolved_name MI_SOURCE_PARAM) mi_attr_noexcept; + + +mi_decl_nodiscard mi_decl_export void* mi_source_new(size_t size MI_SOURCE_PARAM) mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export void* mi_source_new_aligned(size_t size, size_t alignment MI_SOURCE_PARAM) mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); +mi_decl_nodiscard mi_decl_export void* mi_source_new_nothrow(size_t size MI_SOURCE_PARAM) mi_attr_malloc mi_attr_alloc_size(1); +mi_decl_nodiscard mi_decl_export void* mi_source_new_aligned_nothrow(size_t size, size_t alignment MI_SOURCE_PARAM) mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2); + + +// ---------------------------------------------------------------------- +// end of extern "C" +// ---------------------------------------------------------------------- #ifdef __cplusplus } #endif @@ -420,4 +472,7 @@ template bool operator==(const mi_stl_allocator& , const template bool operator!=(const mi_stl_allocator& , const mi_stl_allocator& ) mi_attr_noexcept { return false; } #endif // __cplusplus -#endif + + +#endif // MIMALLOC_H + diff --git a/src/alloc-aligned.c b/src/alloc-aligned.c index c65f5615..fc3cdee9 100644 --- a/src/alloc-aligned.c +++ b/src/alloc-aligned.c @@ -93,52 +93,55 @@ static inline void* mi_heapx_calloc_aligned(mi_heap_t* heap, size_t count, size_ } mi_decl_allocator void* mi_heap_malloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_malloc_aligned_at(heap, size, alignment, offset MI_SOURCE_RET); + return mi_heapx_malloc_aligned_at(heap, size, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_malloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { - return _mi_heapx_malloc_aligned(heap, size, alignment MI_SOURCE_RET); + return _mi_heapx_malloc_aligned(heap, size, alignment MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_zalloc_aligned_at(mi_heap_t* heap, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_zalloc_aligned_at(heap, size, alignment, offset MI_SOURCE_RET); + return mi_heapx_zalloc_aligned_at(heap, size, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_zalloc_aligned(mi_heap_t* heap, size_t size, size_t alignment) mi_attr_noexcept { - return mi_heapx_zalloc_aligned(heap, size, alignment MI_SOURCE_RET); + return mi_heapx_zalloc_aligned(heap, size, alignment MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_calloc_aligned_at(mi_heap_t* heap, size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_calloc_aligned_at(heap, count, size, alignment, offset MI_SOURCE_RET); + return mi_heapx_calloc_aligned_at(heap, count, size, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_calloc_aligned(mi_heap_t* heap, size_t count, size_t size, size_t alignment) mi_attr_noexcept { - return mi_heapx_calloc_aligned(heap, count, size, alignment MI_SOURCE_RET); + return mi_heapx_calloc_aligned(heap, count, size, alignment MI_SOURCE_RET()); } mi_decl_allocator void* mi_malloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_malloc_aligned_at(mi_get_default_heap(), size, alignment, offset MI_SOURCE_RET); + return mi_heapx_malloc_aligned_at(mi_get_default_heap(), size, alignment, offset MI_SOURCE_RET()); } +mi_decl_allocator void* mi_source_malloc_aligned(size_t size, size_t alignment MI_SOURCE_PARAM) mi_attr_noexcept { + return _mi_heapx_malloc_aligned(mi_get_default_heap(), size, alignment MI_SOURCE_ARG); +} mi_decl_allocator void* mi_malloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { - return _mi_heapx_malloc_aligned(mi_get_default_heap(), size, alignment MI_SOURCE_RET); + return mi_source_malloc_aligned(size, alignment MI_SOURCE_RET()); } mi_decl_allocator void* mi_zalloc_aligned_at(size_t size, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_zalloc_aligned_at(mi_get_default_heap(), size, alignment, offset MI_SOURCE_RET); + return mi_heapx_zalloc_aligned_at(mi_get_default_heap(), size, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_zalloc_aligned(size_t size, size_t alignment) mi_attr_noexcept { - return mi_heapx_zalloc_aligned(mi_get_default_heap(), size, alignment MI_SOURCE_RET); + return mi_heapx_zalloc_aligned(mi_get_default_heap(), size, alignment MI_SOURCE_RET()); } mi_decl_allocator void* mi_calloc_aligned_at(size_t count, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_calloc_aligned_at(mi_get_default_heap(), count, size, alignment, offset MI_SOURCE_RET); + return mi_heapx_calloc_aligned_at(mi_get_default_heap(), count, size, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_calloc_aligned(size_t count, size_t size, size_t alignment) mi_attr_noexcept { - return mi_heapx_calloc_aligned(mi_get_default_heap(), count, size, alignment MI_SOURCE_RET); + return mi_heapx_calloc_aligned(mi_get_default_heap(), count, size, alignment MI_SOURCE_RET()); } @@ -209,54 +212,54 @@ static inline void* mi_heapx_recalloc_aligned(mi_heap_t* heap, void* p, size_t n } mi_decl_allocator void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_realloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset MI_SOURCE_RET); + return mi_heapx_realloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept { - return mi_heapx_realloc_aligned(mi_get_default_heap(), p, newsize, alignment MI_SOURCE_RET); + return mi_heapx_realloc_aligned(mi_get_default_heap(), p, newsize, alignment MI_SOURCE_RET()); } mi_decl_allocator void* mi_rezalloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_rezalloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset MI_SOURCE_RET); + return mi_heapx_rezalloc_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_rezalloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept { - return mi_heapx_rezalloc_aligned(mi_get_default_heap(), p, newsize, alignment MI_SOURCE_RET); + return mi_heapx_rezalloc_aligned(mi_get_default_heap(), p, newsize, alignment MI_SOURCE_RET()); } mi_decl_allocator void* mi_recalloc_aligned_at(void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_recalloc_aligned_at(mi_get_default_heap(), p, newcount, size, alignment, offset MI_SOURCE_RET); + return mi_heapx_recalloc_aligned_at(mi_get_default_heap(), p, newcount, size, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_recalloc_aligned(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { - return mi_heapx_recalloc_aligned(mi_get_default_heap(), p, newcount, size, alignment MI_SOURCE_RET); + return mi_heapx_recalloc_aligned(mi_get_default_heap(), p, newcount, size, alignment MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_realloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_realloc_aligned_at(heap, p, newsize, alignment, offset MI_SOURCE_RET); + return mi_heapx_realloc_aligned_at(heap, p, newsize, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_realloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept { - return mi_heapx_realloc_aligned(heap, p, newsize, alignment MI_SOURCE_RET); + return mi_heapx_realloc_aligned(heap, p, newsize, alignment MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_rezalloc_aligned_at(mi_heap_t* heap, void* p, size_t newsize, size_t alignment, size_t offset) mi_attr_noexcept { - return mi_heapx_rezalloc_aligned_at(heap, p, newsize, alignment, offset MI_SOURCE_RET); + return mi_heapx_rezalloc_aligned_at(heap, p, newsize, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_rezalloc_aligned(mi_heap_t* heap, void* p, size_t newsize, size_t alignment) mi_attr_noexcept { - return mi_heapx_rezalloc_aligned(heap, p, newsize, alignment MI_SOURCE_RET); + return mi_heapx_rezalloc_aligned(heap, p, newsize, alignment MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_recalloc_aligned_at(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment, size_t offset) mi_attr_noexcept { size_t total; if (mi_count_size_overflow(newcount, size, &total)) return NULL; - return mi_heapx_rezalloc_aligned_at(heap, p, total, alignment, offset MI_SOURCE_RET); + return mi_heapx_rezalloc_aligned_at(heap, p, total, alignment, offset MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept { size_t total; if (mi_count_size_overflow(newcount, size, &total)) return NULL; - return mi_heapx_rezalloc_aligned(heap, p, total, alignment MI_SOURCE_RET); + return mi_heapx_rezalloc_aligned(heap, p, total, alignment MI_SOURCE_RET()); } diff --git a/src/alloc-posix.c b/src/alloc-posix.c index a8657463..1d5388ad 100644 --- a/src/alloc-posix.c +++ b/src/alloc-posix.c @@ -48,13 +48,12 @@ int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept if (p == NULL) return EINVAL; if (alignment % sizeof(void*) != 0) return EINVAL; // natural alignment if (!_mi_is_power_of_two(alignment)) return EINVAL; // not a power of 2 - mi_heap_t* heap = mi_get_default_heap(); void* q; if (alignment <= MI_MAX_ALIGN_SIZE) { - q = _mi_heapx_malloc(heap, size MI_SOURCE_RET); + q = mi_source_malloc(size MI_SOURCE_RET()); } else { - q = _mi_heapx_malloc_aligned(heap, size, alignment MI_SOURCE_RET); + q = mi_source_malloc_aligned(size, alignment MI_SOURCE_RET()); } if (q==NULL && size != 0) return ENOMEM; mi_assert_internal(((uintptr_t)q % alignment) == 0); @@ -63,47 +62,44 @@ int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept } void* mi_memalign(size_t alignment, size_t size) mi_attr_noexcept { - mi_heap_t* heap = mi_get_default_heap(); void* p; if (alignment <= MI_MAX_ALIGN_SIZE) { - p = _mi_heapx_malloc(heap, size MI_SOURCE_RET); + p = mi_source_malloc(size MI_SOURCE_RET()); } else { - p = _mi_heapx_malloc_aligned(heap, size, alignment MI_SOURCE_RET); + p = mi_source_malloc_aligned(size, alignment MI_SOURCE_RET()); } mi_assert_internal(((uintptr_t)p % alignment) == 0); return p; } void* mi_valloc(size_t size) mi_attr_noexcept { - return _mi_heapx_malloc_aligned(mi_get_default_heap(), size, _mi_os_page_size() MI_SOURCE_RET); + return mi_source_malloc_aligned(size, _mi_os_page_size() MI_SOURCE_RET()); } void* mi_pvalloc(size_t size) mi_attr_noexcept { size_t psize = _mi_os_page_size(); if (size >= SIZE_MAX - psize) return NULL; // overflow size_t asize = ((size + psize - 1) / psize) * psize; - return _mi_heapx_malloc_aligned(mi_get_default_heap(), asize, psize MI_SOURCE_RET); + return mi_source_malloc_aligned(asize, psize MI_SOURCE_RET()); } void* mi_aligned_alloc(size_t alignment, size_t size) mi_attr_noexcept { if (alignment==0 || !_mi_is_power_of_two(alignment)) return NULL; if ((size&(alignment-1)) != 0) return NULL; // C11 requires integral multiple, see - mi_heap_t* heap = mi_get_default_heap(); void* p; if (alignment <= MI_MAX_ALIGN_SIZE) { - p = _mi_heapx_malloc(heap, size MI_SOURCE_RET); + p = mi_source_malloc(size MI_SOURCE_RET()); } else { - p = _mi_heapx_malloc_aligned(heap, size, alignment MI_SOURCE_RET); + p = mi_source_malloc_aligned(size, alignment MI_SOURCE_RET()); } mi_assert_internal(((uintptr_t)p % alignment) == 0); return p; } void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept { // BSD - mi_heap_t* heap = mi_get_default_heap(); - void* newp = _mi_heapx_reallocn(heap, p, count, size MI_SOURCE_RET); + void* newp = mi_source_reallocn(p, count, size MI_SOURCE_RET()); if (newp==NULL) errno = ENOMEM; return newp; } @@ -119,7 +115,7 @@ unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept { size_t len; for(len = 0; s[len] != 0; len++) { } size_t size = (len+1)*sizeof(unsigned short); - unsigned short* p = (unsigned short*)_mi_heapx_malloc(mi_get_default_heap(), size MI_SOURCE_RET); + unsigned short* p = (unsigned short*)mi_source_malloc(size MI_SOURCE_RET()); if (p != NULL) { memcpy(p,s,size); } @@ -127,7 +123,7 @@ unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept { } unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept { - return (unsigned char*)_mi_heapx_strdup(mi_get_default_heap(), (const char*)s MI_SOURCE_RET); + return (unsigned char*)mi_source_strdup((const char*)s MI_SOURCE_RET()); } int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept { @@ -139,7 +135,7 @@ int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept { *buf = NULL; } else { - *buf = _mi_heapx_strdup(mi_get_default_heap(), p MI_SOURCE_RET); + *buf = mi_source_strdup(p MI_SOURCE_RET()); if (*buf==NULL) return ENOMEM; if (size != NULL) *size = strlen(p); } diff --git a/src/alloc.c b/src/alloc.c index 5e5c7d21..eae669ad 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -50,7 +50,7 @@ extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t siz mi_assert_internal(delta >= 0 && mi_page_usable_block_size(page) >= (size - MI_PADDING_SIZE + delta)); padding->canary = (uint32_t)(mi_ptr_encode(page,block,page->keys)); padding->delta = (uint32_t)(delta); - padding->source = source; + padding->source = __mi_source; uint8_t* fill = (uint8_t*)padding - delta; const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // set at most N initial padding bytes for (size_t i = 0; i < maxpad; i++) { fill[i] = MI_DEBUG_PADDING; } @@ -76,11 +76,11 @@ static inline mi_decl_allocator void* mi_heapx_malloc_small(mi_heap_t* heap, siz } extern inline mi_decl_allocator void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept { - return mi_heapx_malloc_small(heap, size MI_SOURCE_RET); + return mi_heapx_malloc_small(heap, size MI_SOURCE_RET()); } extern inline mi_decl_allocator void* mi_malloc_small(size_t size) mi_attr_noexcept { - return mi_heapx_malloc_small(mi_get_default_heap(), size MI_SOURCE_RET); + return mi_heapx_malloc_small(mi_get_default_heap(), size MI_SOURCE_RET()); } // The main allocation function @@ -104,10 +104,13 @@ inline mi_decl_allocator void* _mi_heapx_malloc(mi_heap_t* heap, size_t size MI_ } extern inline mi_decl_allocator void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept { - return _mi_heapx_malloc(heap, size MI_SOURCE_RET); + return _mi_heapx_malloc(heap, size MI_SOURCE_RET()); +} +extern inline mi_decl_allocator void* mi_source_malloc(size_t size MI_SOURCE_PARAM) mi_attr_noexcept { + return _mi_heapx_malloc(mi_get_default_heap(), size MI_SOURCE_ARG); } extern inline mi_decl_allocator void* mi_malloc(size_t size) mi_attr_noexcept { - return _mi_heapx_malloc(mi_get_default_heap(), size MI_SOURCE_RET); + return mi_source_malloc(size MI_SOURCE_RET()); } @@ -131,7 +134,7 @@ void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size) { // zero initialized small block mi_decl_allocator void* mi_zalloc_small(size_t size) mi_attr_noexcept { - void* p = mi_heapx_malloc_small(mi_get_default_heap(), size MI_SOURCE_RET); + void* p = mi_heapx_malloc_small(mi_get_default_heap(), size MI_SOURCE_RET()); if (p != NULL) { _mi_block_zero_init(_mi_ptr_page(p), p, size); // todo: can we avoid getting the page again? } @@ -151,11 +154,11 @@ static inline mi_decl_allocator void* mi_heapx_zalloc(mi_heap_t* heap, size_t si } extern inline mi_decl_allocator void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept { - return mi_heapx_zalloc(heap, size MI_SOURCE_RET); + return mi_heapx_zalloc(heap, size MI_SOURCE_RET()); } mi_decl_allocator void* mi_zalloc(size_t size) mi_attr_noexcept { - return mi_heapx_zalloc(mi_get_default_heap(), size MI_SOURCE_RET); + return mi_heapx_zalloc(mi_get_default_heap(), size MI_SOURCE_RET()); } @@ -542,11 +545,13 @@ static inline mi_decl_allocator void* mi_heapx_calloc(mi_heap_t* heap, size_t co } mi_decl_allocator void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept { - return mi_heapx_calloc(heap, count, size MI_SOURCE_RET); + return mi_heapx_calloc(heap, count, size MI_SOURCE_RET()); +} +mi_decl_allocator void* mi_source_calloc(size_t count, size_t size MI_SOURCE_PARAM) mi_attr_noexcept { + return mi_heapx_calloc(mi_get_default_heap(), count, size MI_SOURCE_ARG); } - mi_decl_allocator void* mi_calloc(size_t count, size_t size) mi_attr_noexcept { - return mi_heapx_calloc(mi_get_default_heap(), count, size MI_SOURCE_RET); + return mi_source_calloc(count, size MI_SOURCE_RET()); } // Uninitialized `calloc` @@ -557,11 +562,11 @@ static inline mi_decl_allocator void* mi_heapx_mallocn(mi_heap_t* heap, size_t c } extern mi_decl_allocator void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept { - return mi_heapx_mallocn(heap, count, size MI_SOURCE_RET); + return mi_heapx_mallocn(heap, count, size MI_SOURCE_RET()); } mi_decl_allocator void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept { - return mi_heapx_mallocn(mi_get_default_heap(), count, size MI_SOURCE_RET); + return mi_heapx_mallocn(mi_get_default_heap(), count, size MI_SOURCE_RET()); } // Expand in place or fail @@ -597,7 +602,7 @@ static mi_decl_allocator void* mi_heapx_realloc(mi_heap_t* heap, void* p, size_t mi_decl_allocator void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { - return mi_heapx_realloc(heap, p, newsize MI_SOURCE_RET); + return mi_heapx_realloc(heap, p, newsize MI_SOURCE_RET()); } mi_decl_allocator void* _mi_heapx_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size MI_SOURCE_PARAM) mi_attr_noexcept { @@ -607,49 +612,55 @@ mi_decl_allocator void* _mi_heapx_reallocn(mi_heap_t* heap, void* p, size_t coun } mi_decl_allocator void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept { - return _mi_heapx_reallocn(heap, p, count, size MI_SOURCE_RET); + return _mi_heapx_reallocn(heap, p, count, size MI_SOURCE_RET()); } // Reallocate but free `p` on errors mi_decl_allocator void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { - void* newp = mi_heapx_realloc(heap, p, newsize MI_SOURCE_RET); + void* newp = mi_heapx_realloc(heap, p, newsize MI_SOURCE_RET()); if (newp==NULL && p!=NULL) mi_free(p); return newp; } mi_decl_allocator void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept { - return _mi_heapx_realloc_zero(heap, p, newsize, true MI_SOURCE_RET); + return _mi_heapx_realloc_zero(heap, p, newsize, true MI_SOURCE_RET()); } mi_decl_allocator void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept { size_t total; if (mi_count_size_overflow(count, size, &total)) return NULL; - return _mi_heapx_realloc_zero(heap, p, total, true MI_SOURCE_RET); + return _mi_heapx_realloc_zero(heap, p, total, true MI_SOURCE_RET()); } +mi_decl_allocator void* mi_source_realloc(void* p, size_t newsize MI_SOURCE_PARAM) mi_attr_noexcept { + return mi_heapx_realloc(mi_get_default_heap(), p, newsize MI_SOURCE_ARG); +} mi_decl_allocator void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept { - return mi_heapx_realloc(mi_get_default_heap(),p,newsize MI_SOURCE_RET); + return mi_source_realloc(p, newsize MI_SOURCE_RET()); } +mi_decl_allocator void* mi_source_reallocn(void* p, size_t count, size_t size MI_SOURCE_PARAM) mi_attr_noexcept { + return _mi_heapx_reallocn(mi_get_default_heap(), p, count, size MI_SOURCE_ARG); +} mi_decl_allocator void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept { - return _mi_heapx_reallocn(mi_get_default_heap(),p,count,size MI_SOURCE_RET); + return mi_source_reallocn(p,count,size MI_SOURCE_RET()); } // Reallocate but free `p` on errors mi_decl_allocator void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept { - void* newp = mi_heapx_realloc(mi_get_default_heap(), p, newsize MI_SOURCE_RET); + void* newp = mi_heapx_realloc(mi_get_default_heap(), p, newsize MI_SOURCE_RET()); if (newp==NULL && p!=NULL) mi_free(p); return newp; } mi_decl_allocator void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept { - return _mi_heapx_realloc_zero(mi_get_default_heap(), p, newsize, true MI_SOURCE_RET); + return _mi_heapx_realloc_zero(mi_get_default_heap(), p, newsize, true MI_SOURCE_RET()); } mi_decl_allocator void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_noexcept { size_t total; if (mi_count_size_overflow(count, size, &total)) return NULL; - return _mi_heapx_realloc_zero(mi_get_default_heap(), p, total, true MI_SOURCE_RET); + return _mi_heapx_realloc_zero(mi_get_default_heap(), p, total, true MI_SOURCE_RET()); } @@ -659,7 +670,7 @@ mi_decl_allocator void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_ // ------------------------------------------------------ // `strdup` using mi_malloc -mi_decl_allocator char* _mi_heapx_strdup(mi_heap_t* heap, const char* s MI_SOURCE_PARAM) mi_attr_noexcept { +static char* mi_heapx_strdup(mi_heap_t* heap, const char* s MI_SOURCE_PARAM) mi_attr_noexcept { if (s == NULL) return NULL; size_t n = strlen(s); char* t = (char*)_mi_heapx_malloc(heap, n+1 MI_SOURCE_ARG); @@ -668,10 +679,13 @@ mi_decl_allocator char* _mi_heapx_strdup(mi_heap_t* heap, const char* s MI_SOUR } char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept { - return _mi_heapx_strdup(heap, s MI_SOURCE_RET); + return mi_heapx_strdup(heap, s MI_SOURCE_RET()); +} +char* mi_source_strdup(const char* s MI_SOURCE_PARAM) mi_attr_noexcept { + return mi_heapx_strdup(mi_get_default_heap(), s MI_SOURCE_ARG); } char* mi_strdup(const char* s) mi_attr_noexcept { - return _mi_heapx_strdup(mi_get_default_heap(), s MI_SOURCE_RET); + return mi_source_strdup(s MI_SOURCE_RET()); } // `strndup` using mi_malloc @@ -687,10 +701,13 @@ static char* mi_heapx_strndup(mi_heap_t* heap, const char* s, size_t n MI_SOURC } char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept { - return mi_heapx_strndup(heap, s, n MI_SOURCE_RET); + return mi_heapx_strndup(heap, s, n MI_SOURCE_RET()); +} +char* mi_source_strndup(const char* s, size_t n MI_SOURCE_PARAM) mi_attr_noexcept { + return mi_heapx_strndup(mi_get_default_heap(), s, n MI_SOURCE_ARG); } char* mi_strndup(const char* s, size_t n) mi_attr_noexcept { - return mi_heapx_strndup(mi_get_default_heap(), s, n MI_SOURCE_RET); + return mi_source_strndup(s, n MI_SOURCE_RET()); } #ifndef __wasi__ @@ -747,11 +764,13 @@ static char* mi_heapx_realpath(mi_heap_t* heap, const char* fname, char* resolve #endif char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept { - return mi_heapx_realpath(heap, fname, resolved_name MI_SOURCE_RET); + return mi_heapx_realpath(heap, fname, resolved_name MI_SOURCE_RET()); +} +char* mi_source_realpath(const char* fname, char* resolved_name MI_SOURCE_PARAM) mi_attr_noexcept { + return mi_heapx_realpath(mi_get_default_heap(), fname, resolved_name MI_SOURCE_ARG); } - char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept { - return mi_heapx_realpath(mi_get_default_heap(), fname, resolved_name MI_SOURCE_RET); + return mi_heapx_realpath(mi_get_default_heap(), fname, resolved_name MI_SOURCE_RET()); } #endif @@ -807,52 +826,62 @@ static bool mi_try_new_handler(bool nothrow) { } #endif -static mi_decl_noinline void* mi_heapx_try_new(mi_heap_t* heap, size_t size, bool nothrow MI_SOURCE_PARAM) { +static mi_decl_noinline void* mi_source_try_new(size_t size, bool nothrow MI_SOURCE_PARAM) { void* p = NULL; while(p == NULL && mi_try_new_handler(nothrow)) { - p = _mi_heapx_malloc(heap, size MI_SOURCE_ARG); + p = mi_source_malloc(size MI_SOURCE_ARG); } return p; } -static inline void* mi_heapx_new(size_t size MI_SOURCE_PARAM) { - mi_heap_t* const heap = mi_get_default_heap(); - void* p = _mi_heapx_malloc(heap, size MI_SOURCE_ARG); - if (mi_unlikely(p == NULL)) return mi_heapx_try_new(heap, size, false MI_SOURCE_ARG); +inline void* mi_source_new(size_t size MI_SOURCE_PARAM) { + void* p = mi_source_malloc(size MI_SOURCE_ARG); + if (mi_unlikely(p == NULL)) return mi_source_try_new(size, false MI_SOURCE_ARG); return p; } void* mi_new(size_t size) { - return mi_heapx_new(size MI_SOURCE_RET); + return mi_source_new(size MI_SOURCE_RET()); } -void* mi_new_nothrow(size_t size) { - mi_heap_t* const heap = mi_get_default_heap(); - void* p = _mi_heapx_malloc(heap, size MI_SOURCE_RET); - if (mi_unlikely(p == NULL)) return mi_heapx_try_new(heap, size, true MI_SOURCE_RET); +void* mi_source_new_nothrow(size_t size MI_SOURCE_PARAM) { + void* p = mi_source_malloc(size MI_SOURCE_ARG); + if (mi_unlikely(p == NULL)) return mi_source_try_new(size, true MI_SOURCE_ARG); return p; } -void* mi_new_aligned(size_t size, size_t alignment) { - mi_heap_t* const heap = mi_get_default_heap(); +void* mi_new_nothrow(size_t size) { + return mi_source_new_nothrow(size MI_SOURCE_RET()); +} + + +void* mi_source_new_aligned(size_t size, size_t alignment MI_SOURCE_PARAM) { void* p; do { - p = _mi_heapx_malloc_aligned(heap, size, alignment MI_SOURCE_RET); + p = mi_source_malloc_aligned(size, alignment MI_SOURCE_ARG); } while(p == NULL && mi_try_new_handler(false)); return p; } -void* mi_new_aligned_nothrow(size_t size, size_t alignment) { - mi_heap_t* const heap = mi_get_default_heap(); +void* mi_new_aligned(size_t size, size_t alignment) { + return mi_source_new_aligned(size, alignment MI_SOURCE_RET()); +} + +void* mi_source_new_aligned_nothrow(size_t size, size_t alignment MI_SOURCE_PARAM) { void* p; do { - p = _mi_heapx_malloc_aligned(heap, size, alignment MI_SOURCE_RET); + p = mi_source_malloc_aligned(size, alignment MI_SOURCE_ARG); } while(p == NULL && mi_try_new_handler(true)); return p; } +void* mi_new_aligned_nothrow(size_t size, size_t alignment) { + return mi_source_new_aligned_nothrow(size, alignment MI_SOURCE_RET()); +} + + void* mi_new_n(size_t count, size_t size) { size_t total; if (mi_unlikely(mi_count_size_overflow(count, size, &total))) { @@ -860,7 +889,7 @@ void* mi_new_n(size_t count, size_t size) { return NULL; } else { - return mi_heapx_new(total MI_SOURCE_RET); + return mi_source_new(total MI_SOURCE_RET()); } } @@ -868,7 +897,7 @@ void* mi_new_realloc(void* p, size_t newsize) { mi_heap_t* const heap = mi_get_default_heap(); void* q; do { - q = mi_heapx_realloc(heap, p, newsize MI_SOURCE_RET); + q = mi_heapx_realloc(heap, p, newsize MI_SOURCE_RET()); } while (q == NULL && mi_try_new_handler(false)); return q; } @@ -882,7 +911,7 @@ void* mi_new_reallocn(void* p, size_t newcount, size_t size) { } void* q; do { - q = mi_heapx_realloc(heap, p, total MI_SOURCE_RET); + q = mi_heapx_realloc(heap, p, total MI_SOURCE_RET()); } while (q == NULL && mi_try_new_handler(false)); return q; } diff --git a/src/options.c b/src/options.c index 1b12adb2..79ef47a1 100644 --- a/src/options.c +++ b/src/options.c @@ -51,7 +51,7 @@ typedef struct mi_option_desc_s { static mi_option_desc_t options[_mi_option_last] = { // stable options - { MI_DEBUG, UNINIT, MI_OPTION(show_errors) }, + { 1, UNINIT, MI_OPTION(show_errors) }, { 0, UNINIT, MI_OPTION(show_stats) }, { 0, UNINIT, MI_OPTION(verbose) }, @@ -381,33 +381,73 @@ void _mi_error_message(int err, const char* fmt, ...) { mi_call_error_handler(err); } -#if defined(MI_PADDING) && defined(MI_ENCODE_FREELIST) -const char* _mi_debug_fname_base = "mimalloc_fname_base"; -#endif +// ----------------------------------------------------------------------------------------------- +// compressed location: +// lsb=1: bit 63-19: relative file name char* (to `mi_fname_base`), bit 18-1: line number +// lsb=0: bit 63-01: return address +// ----------------------------------------------------------------------------------------------- +static const char* mi_debug_fname_base = "mimalloc_fname_base"; + +#define MI_FNAME_SHIFT 16 +#define MI_LINE_SHIFT (MI_FNAME_SHIFT + MI_INTPTR_SHIFT) +#define MI_LINE_MASK ((1L << MI_LINE_SHIFT) - 1) + +mi_source_t mi_source_ret(void* return_address) { + mi_source_t source = { ((intptr_t)return_address << 1) }; + return source; +} + +mi_source_t mi_source_loc(const char* fname, int lineno ) { + ptrdiff_t delta = fname - mi_debug_fname_base; + mi_assert_internal(((delta << MI_FNAME_SHIFT) >> MI_FNAME_SHIFT) == delta); + mi_source_t source = { ((((intptr_t)delta) << MI_FNAME_SHIFT) | ((lineno << 1) & MI_LINE_MASK) | 1) }; + return source; +} + +void* mi_source_unpack(mi_source_t source, const char** fname, int* lineno) { + *fname = NULL; + *lineno = 0; + if (source.src == 0) { + return NULL; + } + else if ((source.src & 1) == 1) { + *fname = (const char*)(mi_debug_fname_base + ((source.src >> MI_LINE_SHIFT) << MI_INTPTR_SHIFT) ); + *lineno = (source.src & MI_LINE_MASK) >> 1; + return NULL; + } + else { + return ((void*)(source.src >> 1)); + } +} + +// ----------------------------------------------------------------------------------------------- +// Error message for a specific heap block +// ----------------------------------------------------------------------------------------------- void _mi_page_block_error_message(int err, const mi_page_t* page, const mi_block_t* block, const char* msg) { #if defined(MI_PADDING) && defined(MI_ENCODE_FREELIST) const size_t bsize = mi_page_usable_block_size(page); const mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + bsize); const size_t size = (padding->delta <= bsize ? bsize - padding->delta : bsize); - if (padding->source==0) { - mi_show_error_message("%s: at block %p of size %zu\n", msg, block, size); - } - else if ((padding->source & 1) == 0) { + const char* fname; + int lineno; + void* return_addr = mi_source_unpack(padding->source, &fname, &lineno); + if (return_addr != NULL) { #ifdef _MSC_VER const char* hint = " hint: paste the code address in the disassembly window in the debugger to find the source location.\n"; #else const char* hint = ""; #endif - mi_show_error_message("%s: at block %p of size %zu allocated at 0x%p.\n%s", msg, block, size, (void*)(padding->source >> 1), hint); + mi_show_error_message("%s: at block %p of size %zu allocated at 0x%p.\n%s", msg, block, size, return_addr, hint); + } + else if (fname != NULL) { + mi_show_error_message("%s: at block %p of size %zu allocated at %s:%i.\n", msg, block, size, fname, lineno); } else { - const char* fname = _mi_debug_fname_base + ((int32_t)(padding->source >> 32)); - size_t lineno = ((uint32_t)padding->source) >> 1; - mi_show_error_message("%s: at block %p of size %zu allocated at %s:%zu", msg, block, size, fname, lineno); + mi_show_error_message("%s: at block %p of size %zu.\n", msg, block, mi_page_usable_block_size(page)); } #else - mi_show_error_message("%s: at block %p of size %zu", msg, block, mi_page_usable_block_size(page)); + mi_show_error_message("%s: at block %p of size %zu.\n", msg, block, mi_page_usable_block_size(page)); #endif mi_call_error_handler(err); } diff --git a/test/main-override.cpp b/test/main-override.cpp index 958bfa56..378b89db 100644 --- a/test/main-override.cpp +++ b/test/main-override.cpp @@ -4,7 +4,9 @@ #include #include +#include #include +#include #include #include @@ -57,8 +59,16 @@ int main() { static void dangling_ptr_write() { for (int i = 0; i < 1000; i++) { - uint8_t* p = new uint8_t[16]; - free(p); + uint8_t* p; + if ((i & 1) == 0) { + p = (uint8_t*)malloc(16); + free(p); + } + else { + p = new uint8_t[16]; + // delete p; // delete sets the pointer to an invalid value generally + free(p); + } p[0] = 0; } }