diff --git a/include/mimalloc.h b/include/mimalloc.h index e526725e..1f12a41e 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -297,6 +297,8 @@ typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_ mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg); mi_decl_export void mi_heap_print_json(mi_heap_t* heap, mi_output_fun* out, void* arg); +mi_decl_export bool mi_heap_is_empty(mi_heap_t* heap); +mi_decl_export void mi_heap_check_leak(mi_heap_t* heap, mi_output_fun* out, void* arg); // Experimental mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept; diff --git a/src/heap.c b/src/heap.c index 4bfd1b5a..338f0c0c 100644 --- a/src/heap.c +++ b/src/heap.c @@ -574,6 +574,7 @@ typedef struct mi_print_json_s { } mi_print_json_t; static bool mi_heap_print_json_visit(const mi_heap_t* heap, const mi_heap_area_t* area, const mi_block_info_t* info, void* arg) { + UNUSED(heap); mi_print_json_t* varg = (mi_print_json_t*)(arg); if (info==NULL) { _mi_fprintf(varg->out, varg->out_arg, varg->area_count==0 ? " {" : " ]\n}\n,{"); @@ -599,8 +600,21 @@ static bool mi_heap_print_json_visit(const mi_heap_t* heap, const mi_heap_area_t void mi_heap_print_json(mi_heap_t* heap, mi_output_fun* out, void* arg) { if (heap==NULL) heap = mi_heap_get_default(); mi_print_json_t info = { 0, 0, out, arg }; - _mi_fprintf(info.out, info.out_arg, "{ \"heap\": 0x%p, \"thread_id\": 0x%zx, \"page_count\": %zu", heap, heap->thread_id, heap->page_count); + _mi_fprintf(info.out, info.out_arg, "{ \"heap\": 0x%p, \"thread_id\": 0x%zx, \"page_count\": %zu, \"block_padding\": %zu", heap, heap->thread_id, heap->page_count, mi_extra_padding() ); _mi_fprintf(info.out, info.out_arg, ", \"pages\": [\n"); mi_heap_visit_blocks(heap, true, &mi_heap_print_json_visit, &info); _mi_fprintf(info.out, info.out_arg, info.area_count==0 ? "]\n" : " ] }\n] }\n"); } + +bool mi_heap_is_empty(mi_heap_t* heap) { + if (heap==NULL) heap = mi_heap_get_default(); + mi_collect(false); + return (heap->page_count == 0); +} + +void mi_heap_check_leak(mi_heap_t* heap, mi_output_fun* out, void* arg) { + if (!mi_heap_is_empty(heap)) { + _mi_fprintf(out,arg,"mimalloc: potential memory leak detected. Current heap blocks:\n"); + mi_heap_print_json(heap, out, arg); + } +} diff --git a/test/main-override-static.c b/test/main-override-static.c index 8aec6358..798b5c5a 100644 --- a/test/main-override-static.c +++ b/test/main-override-static.c @@ -33,7 +33,7 @@ int main() { free(p2); p2 = malloc(16); p1 = realloc(p1, 32); - mi_heap_print_json(NULL,NULL,NULL); + mi_heap_check_leak(NULL,NULL,NULL); free(p1); free(p2); //free(s);