diff --git a/CMakeLists.txt b/CMakeLists.txt
index 019664b4..1387e0db 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,6 +45,7 @@ set(mi_sources
src/bitmap.c
src/heap.c
src/init.c
+ src/libc.c
src/options.c
src/os.c
src/page.c
diff --git a/ide/vs2017/mimalloc-override.vcxproj b/ide/vs2017/mimalloc-override.vcxproj
index 3d5c1f75..6d20eb57 100644
--- a/ide/vs2017/mimalloc-override.vcxproj
+++ b/ide/vs2017/mimalloc-override.vcxproj
@@ -238,6 +238,7 @@
+
diff --git a/ide/vs2017/mimalloc-override.vcxproj.filters b/ide/vs2017/mimalloc-override.vcxproj.filters
index 4c2f30a9..bc08b77a 100644
--- a/ide/vs2017/mimalloc-override.vcxproj.filters
+++ b/ide/vs2017/mimalloc-override.vcxproj.filters
@@ -94,5 +94,8 @@
Source Files
+
+ Source Files
+
\ No newline at end of file
diff --git a/ide/vs2017/mimalloc.vcxproj b/ide/vs2017/mimalloc.vcxproj
index 46eb05d8..ece9a14d 100644
--- a/ide/vs2017/mimalloc.vcxproj
+++ b/ide/vs2017/mimalloc.vcxproj
@@ -227,6 +227,7 @@
+
diff --git a/ide/vs2017/mimalloc.vcxproj.filters b/ide/vs2017/mimalloc.vcxproj.filters
index c921243c..3f055517 100644
--- a/ide/vs2017/mimalloc.vcxproj.filters
+++ b/ide/vs2017/mimalloc.vcxproj.filters
@@ -65,6 +65,9 @@
Source Files
+
+ Source Files
+
diff --git a/ide/vs2019/mimalloc-override.vcxproj b/ide/vs2019/mimalloc-override.vcxproj
index 1c5c61b7..a84a5178 100644
--- a/ide/vs2019/mimalloc-override.vcxproj
+++ b/ide/vs2019/mimalloc-override.vcxproj
@@ -238,6 +238,7 @@
+
diff --git a/ide/vs2019/mimalloc-override.vcxproj.filters b/ide/vs2019/mimalloc-override.vcxproj.filters
index 644345a7..6b535240 100644
--- a/ide/vs2019/mimalloc-override.vcxproj.filters
+++ b/ide/vs2019/mimalloc-override.vcxproj.filters
@@ -55,6 +55,9 @@
Source Files
+
+ Source Files
+
diff --git a/ide/vs2019/mimalloc.vcxproj b/ide/vs2019/mimalloc.vcxproj
index 0e2eb312..0076b1db 100644
--- a/ide/vs2019/mimalloc.vcxproj
+++ b/ide/vs2019/mimalloc.vcxproj
@@ -219,6 +219,7 @@
+
true
diff --git a/ide/vs2019/mimalloc.vcxproj.filters b/ide/vs2019/mimalloc.vcxproj.filters
index 235699e4..8234f46b 100644
--- a/ide/vs2019/mimalloc.vcxproj.filters
+++ b/ide/vs2019/mimalloc.vcxproj.filters
@@ -58,6 +58,9 @@
Source Files
+
+ Source Files
+
diff --git a/ide/vs2022/mimalloc-override.vcxproj b/ide/vs2022/mimalloc-override.vcxproj
index e2c7f71d..df2a0816 100644
--- a/ide/vs2022/mimalloc-override.vcxproj
+++ b/ide/vs2022/mimalloc-override.vcxproj
@@ -240,6 +240,7 @@
+
true
diff --git a/ide/vs2022/mimalloc-override.vcxproj.filters b/ide/vs2022/mimalloc-override.vcxproj.filters
index 0f105c1a..dd69c827 100644
--- a/ide/vs2022/mimalloc-override.vcxproj.filters
+++ b/ide/vs2022/mimalloc-override.vcxproj.filters
@@ -55,6 +55,9 @@
Sources
+
+ Sources
+
diff --git a/ide/vs2022/mimalloc.vcxproj b/ide/vs2022/mimalloc.vcxproj
index c298550a..21a475df 100644
--- a/ide/vs2022/mimalloc.vcxproj
+++ b/ide/vs2022/mimalloc.vcxproj
@@ -219,6 +219,7 @@
+
true
diff --git a/ide/vs2022/mimalloc.vcxproj.filters b/ide/vs2022/mimalloc.vcxproj.filters
index b3cdb3b3..bb5c8ce9 100644
--- a/ide/vs2022/mimalloc.vcxproj.filters
+++ b/ide/vs2022/mimalloc.vcxproj.filters
@@ -55,6 +55,9 @@
Sources
+
+ Sources
+
diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h
index 00d26260..f98a4649 100644
--- a/include/mimalloc/internal.h
+++ b/include/mimalloc/internal.h
@@ -192,14 +192,17 @@ bool _mi_free_delayed_block(mi_block_t* block);
void _mi_free_generic(const mi_segment_t* segment, mi_page_t* page, bool is_local, void* p) mi_attr_noexcept; // for runtime integration
void _mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, const size_t min_size);
-// option.c, c primitives
+// "libc.c"
+#include
+void _mi_vsnprintf(char* buf, size_t bufsize, const char* fmt, va_list args);
+void _mi_snprintf(char* buf, size_t buflen, const char* fmt, ...);
char _mi_toupper(char c);
int _mi_strnicmp(const char* s, const char* t, size_t n);
void _mi_strlcpy(char* dest, const char* src, size_t dest_size);
void _mi_strlcat(char* dest, const char* src, size_t dest_size);
size_t _mi_strlen(const char* s);
size_t _mi_strnlen(const char* s, size_t max_len);
-
+bool _mi_getenv(const char* name, char* result, size_t result_size);
#if MI_DEBUG>1
bool _mi_page_is_valid(mi_page_t* page);
diff --git a/src/arena.c b/src/arena.c
index a04a04c8..f0ee0986 100644
--- a/src/arena.c
+++ b/src/arena.c
@@ -815,7 +815,7 @@ int mi_reserve_os_memory_ex(size_t size, bool commit, bool allow_large, bool exc
const bool is_large = memid.is_pinned; // todo: use separate is_large field?
if (!mi_manage_os_memory_ex2(start, size, is_large, -1 /* numa node */, exclusive, memid, arena_id)) {
_mi_os_free_ex(start, size, commit, memid, &_mi_stats_main);
- _mi_verbose_message("failed to reserve %zu k memory\n", _mi_divide_up(size, 1024));
+ _mi_verbose_message("failed to reserve %zu KiB memory\n", _mi_divide_up(size, 1024));
return ENOMEM;
}
_mi_verbose_message("reserved %zu KiB memory%s\n", _mi_divide_up(size, 1024), is_large ? " (in large os pages)" : "");
diff --git a/src/libc.c b/src/libc.c
new file mode 100644
index 00000000..f1412722
--- /dev/null
+++ b/src/libc.c
@@ -0,0 +1,273 @@
+/* ----------------------------------------------------------------------------
+Copyright (c) 2018-2023, Microsoft Research, Daan Leijen
+This is free software; you can redistribute it and/or modify it under the
+terms of the MIT license. A copy of the license can be found in the file
+"LICENSE" at the root of this distribution.
+-----------------------------------------------------------------------------*/
+
+// --------------------------------------------------------
+// This module defines various std libc functions to reduce
+// the dependency on libc, and also prevent errors caused
+// by some libc implementations when called before `main`
+// executes (due to malloc redirection)
+// --------------------------------------------------------
+
+#include "mimalloc.h"
+#include "mimalloc/internal.h"
+#include "mimalloc/prim.h" // mi_prim_getenv
+
+char _mi_toupper(char c) {
+ if (c >= 'a' && c <= 'z') return (c - 'a' + 'A');
+ else return c;
+}
+
+int _mi_strnicmp(const char* s, const char* t, size_t n) {
+ if (n == 0) return 0;
+ for (; *s != 0 && *t != 0 && n > 0; s++, t++, n--) {
+ if (_mi_toupper(*s) != _mi_toupper(*t)) break;
+ }
+ return (n == 0 ? 0 : *s - *t);
+}
+
+void _mi_strlcpy(char* dest, const char* src, size_t dest_size) {
+ if (dest==NULL || src==NULL || dest_size == 0) return;
+ // copy until end of src, or when dest is (almost) full
+ while (*src != 0 && dest_size > 1) {
+ *dest++ = *src++;
+ dest_size--;
+ }
+ // always zero terminate
+ *dest = 0;
+}
+
+void _mi_strlcat(char* dest, const char* src, size_t dest_size) {
+ if (dest==NULL || src==NULL || dest_size == 0) return;
+ // find end of string in the dest buffer
+ while (*dest != 0 && dest_size > 1) {
+ dest++;
+ dest_size--;
+ }
+ // and catenate
+ _mi_strlcpy(dest, src, dest_size);
+}
+
+size_t _mi_strlen(const char* s) {
+ if (s==NULL) return 0;
+ size_t len = 0;
+ while(s[len] != 0) { len++; }
+ return len;
+}
+
+size_t _mi_strnlen(const char* s, size_t max_len) {
+ if (s==NULL) return 0;
+ size_t len = 0;
+ while(s[len] != 0 && len < max_len) { len++; }
+ return len;
+}
+
+#ifdef MI_NO_GETENV
+bool _mi_getenv(const char* name, char* result, size_t result_size) {
+ MI_UNUSED(name);
+ MI_UNUSED(result);
+ MI_UNUSED(result_size);
+ return false;
+}
+#else
+bool _mi_getenv(const char* name, char* result, size_t result_size) {
+ if (name==NULL || result == NULL || result_size < 64) return false;
+ return _mi_prim_getenv(name,result,result_size);
+}
+#endif
+
+// --------------------------------------------------------
+// Define our own limited `_mi_vsnprintf` and `_mi_snprintf`
+// This is mostly to avoid calling these when libc is not yet
+// initialized (and to reduce dependencies)
+//
+// format: d i, p x u, s
+// prec: z l ll L
+// width: 10
+// align-left: -
+// fill: 0
+// plus: +
+// --------------------------------------------------------
+
+static void mi_outc(char c, char** out, char* end) {
+ char* p = *out;
+ if (p >= end) return;
+ *p = c;
+ *out = p + 1;
+}
+
+static void mi_outs(const char* s, char** out, char* end) {
+ if (s == NULL) return;
+ char* p = *out;
+ while (*s != 0 && p < end) {
+ *p++ = *s++;
+ }
+ *out = p;
+}
+
+static void mi_out_fill(char fill, size_t len, char** out, char* end) {
+ char* p = *out;
+ for (size_t i = 0; i < len && p < end; i++) {
+ *p++ = fill;
+ }
+ *out = p;
+}
+
+static void mi_out_alignright(char fill, char* start, size_t len, size_t extra, char* end) {
+ if (len == 0 || extra == 0) return;
+ if (start + len + extra >= end) return;
+ // move `len` characters to the right (in reverse since it can overlap)
+ for (size_t i = 1; i <= len; i++) {
+ start[len + extra - i] = start[len - i];
+ }
+ // and fill the start
+ for (size_t i = 0; i < extra; i++) {
+ start[i] = fill;
+ }
+}
+
+
+static void mi_out_num(uintptr_t x, size_t base, char prefix, char** out, char* end)
+{
+ if (x == 0 || base == 0 || base > 16) {
+ if (prefix != 0) { mi_outc(prefix, out, end); }
+ mi_outc('0',out,end);
+ }
+ else {
+ // output digits in reverse
+ char* start = *out;
+ while (x > 0) {
+ char digit = (char)(x % base);
+ mi_outc((digit <= 9 ? '0' + digit : 'A' + digit - 10),out,end);
+ x = x / base;
+ }
+ if (prefix != 0) {
+ mi_outc(prefix, out, end);
+ }
+ size_t len = *out - start;
+ // and reverse in-place
+ for (size_t i = 0; i < (len / 2); i++) {
+ char c = start[len - i - 1];
+ start[len - i - 1] = start[i];
+ start[i] = c;
+ }
+ }
+}
+
+
+#define MI_NEXTC() c = *in; if (c==0) break; in++;
+
+void _mi_vsnprintf(char* buf, size_t bufsize, const char* fmt, va_list args) {
+ if (buf == NULL || bufsize == 0 || fmt == NULL) return;
+ buf[bufsize - 1] = 0;
+ char* const end = buf + (bufsize - 1);
+ const char* in = fmt;
+ char* out = buf;
+ while (true) {
+ if (out >= end) break;
+ char c;
+ MI_NEXTC();
+ if (c != '%') {
+ if ((c >= ' ' && c <= '~') || c=='\n' || c=='\r' || c=='\t') { // output visible ascii or standard control only
+ mi_outc(c, &out, end);
+ }
+ }
+ else {
+ MI_NEXTC();
+ char fill = ' ';
+ size_t width = 0;
+ char numtype = 'd';
+ char numplus = 0;
+ bool alignright = true;
+ if (c == '+' || c == ' ') { numplus = c; MI_NEXTC(); }
+ if (c == '-') { alignright = false; MI_NEXTC(); }
+ if (c == '0') { fill = '0'; MI_NEXTC(); }
+ if (c >= '1' && c <= '9') {
+ width = (c - '0'); MI_NEXTC();
+ while (c >= '0' && c <= '9') {
+ width = (10 * width) + (c - '0'); MI_NEXTC();
+ }
+ if (c == 0) break; // extra check due to while
+ }
+ if (c == 'z' || c == 't' || c == 'L') { numtype = c; MI_NEXTC(); }
+ else if (c == 'l') {
+ numtype = c; MI_NEXTC();
+ if (c == 'l') { numtype = 'L'; MI_NEXTC(); }
+ }
+
+ char* start = out;
+ if (c == 's') {
+ // string
+ const char* s = va_arg(args, const char*);
+ mi_outs(s, &out, end);
+ }
+ else if (c == 'p' || c == 'x' || c == 'u') {
+ // unsigned
+ uintptr_t x = 0;
+ if (c == 'x' || c == 'u') {
+ if (numtype == 'z') x = va_arg(args, size_t);
+ else if (numtype == 't') x = va_arg(args, uintptr_t); // unsigned ptrdiff_t
+ else if (numtype == 'L') x = va_arg(args, unsigned long long);
+ else x = va_arg(args, unsigned long);
+ }
+ else if (c == 'p') {
+ x = va_arg(args, uintptr_t);
+ mi_outs("0x", &out, end);
+ start = out;
+ width = (width >= 2 ? width - 2 : 0);
+ }
+ if (width == 0 && (c == 'x' || c == 'p')) {
+ if (c == 'p') { width = 2 * (x <= UINT32_MAX ? 4 : ((x >> 16) <= UINT32_MAX ? 6 : sizeof(void*))); }
+ if (width == 0) { width = 2; }
+ fill = '0';
+ }
+ mi_out_num(x, (c == 'x' || c == 'p' ? 16 : 10), numplus, &out, end);
+ }
+ else if (c == 'i' || c == 'd') {
+ // signed
+ intptr_t x = 0;
+ if (numtype == 'z') x = va_arg(args, intptr_t );
+ else if (numtype == 't') x = va_arg(args, ptrdiff_t);
+ else if (numtype == 'L') x = va_arg(args, long long);
+ else x = va_arg(args, long);
+ char pre = 0;
+ if (x < 0) {
+ pre = '-';
+ if (x > INTPTR_MIN) { x = -x; }
+ }
+ else if (numplus != 0) {
+ pre = numplus;
+ }
+ mi_out_num((uintptr_t)x, 10, pre, &out, end);
+ }
+ else if (c >= ' ' && c <= '~') {
+ // unknown format
+ mi_outc('%', &out, end);
+ mi_outc(c, &out, end);
+ }
+
+ // fill & align
+ mi_assert_internal(out <= end);
+ mi_assert_internal(out >= start);
+ const size_t len = out - start;
+ if (len < width) {
+ mi_out_fill(fill, width - len, &out, end);
+ if (alignright && out <= end) {
+ mi_out_alignright(fill, start, len, width - len, end);
+ }
+ }
+ }
+ }
+ mi_assert_internal(out <= end);
+ *out = 0;
+}
+
+void _mi_snprintf(char* buf, size_t buflen, const char* fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ _mi_vsnprintf(buf, buflen, fmt, args);
+ va_end(args);
+}
diff --git a/src/options.c b/src/options.c
index 345b560e..61dc2914 100644
--- a/src/options.c
+++ b/src/options.c
@@ -9,9 +9,9 @@ terms of the MIT license. A copy of the license can be found in the file
#include "mimalloc/atomic.h"
#include "mimalloc/prim.h" // mi_prim_out_stderr
-#include // FILE
+#include // stdin/stdout
#include // abort
-#include
+
static long mi_max_error_count = 16; // stop outputting errors after this (use < 0 for no limit)
@@ -311,12 +311,12 @@ void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* me
}
// Define our own limited `fprintf` that avoids memory allocation.
-// We do this using `snprintf` with a limited buffer.
+// We do this using `_mi_vsnprintf` with a limited buffer.
static void mi_vfprintf( mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args ) {
char buf[512];
if (fmt==NULL) return;
if (!mi_recurse_enter()) return;
- vsnprintf(buf,sizeof(buf)-1,fmt,args);
+ _mi_vsnprintf(buf, sizeof(buf)-1, fmt, args);
mi_recurse_exit();
_mi_fputs(out,arg,prefix,buf);
}
@@ -331,7 +331,7 @@ void _mi_fprintf( mi_output_fun* out, void* arg, const char* fmt, ... ) {
static void mi_vfprintf_thread(mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args) {
if (prefix != NULL && _mi_strnlen(prefix,33) <= 32 && !_mi_is_main_thread()) {
char tprefix[64];
- snprintf(tprefix, sizeof(tprefix), "%sthread 0x%llx: ", prefix, (unsigned long long)_mi_thread_id());
+ _mi_snprintf(tprefix, sizeof(tprefix), "%sthread 0x%tx: ", prefix, (uintptr_t)_mi_thread_id());
mi_vfprintf(out, arg, tprefix, fmt, args);
}
else {
@@ -434,68 +434,6 @@ void _mi_error_message(int err, const char* fmt, ...) {
// --------------------------------------------------------
// Initialize options by checking the environment
// --------------------------------------------------------
-char _mi_toupper(char c) {
- if (c >= 'a' && c <= 'z') return (c - 'a' + 'A');
- else return c;
-}
-
-int _mi_strnicmp(const char* s, const char* t, size_t n) {
- if (n == 0) return 0;
- for (; *s != 0 && *t != 0 && n > 0; s++, t++, n--) {
- if (_mi_toupper(*s) != _mi_toupper(*t)) break;
- }
- return (n == 0 ? 0 : *s - *t);
-}
-
-void _mi_strlcpy(char* dest, const char* src, size_t dest_size) {
- if (dest==NULL || src==NULL || dest_size == 0) return;
- // copy until end of src, or when dest is (almost) full
- while (*src != 0 && dest_size > 1) {
- *dest++ = *src++;
- dest_size--;
- }
- // always zero terminate
- *dest = 0;
-}
-
-void _mi_strlcat(char* dest, const char* src, size_t dest_size) {
- if (dest==NULL || src==NULL || dest_size == 0) return;
- // find end of string in the dest buffer
- while (*dest != 0 && dest_size > 1) {
- dest++;
- dest_size--;
- }
- // and catenate
- _mi_strlcpy(dest, src, dest_size);
-}
-
-size_t _mi_strlen(const char* s) {
- if (s==NULL) return 0;
- size_t len = 0;
- while(s[len] != 0) { len++; }
- return len;
-}
-
-size_t _mi_strnlen(const char* s, size_t max_len) {
- if (s==NULL) return 0;
- size_t len = 0;
- while(s[len] != 0 && len < max_len) { len++; }
- return len;
-}
-
-#ifdef MI_NO_GETENV
-static bool mi_getenv(const char* name, char* result, size_t result_size) {
- MI_UNUSED(name);
- MI_UNUSED(result);
- MI_UNUSED(result_size);
- return false;
-}
-#else
-static bool mi_getenv(const char* name, char* result, size_t result_size) {
- if (name==NULL || result == NULL || result_size < 64) return false;
- return _mi_prim_getenv(name,result,result_size);
-}
-#endif
// TODO: implement ourselves to reduce dependencies on the C runtime
#include // strtol
@@ -508,11 +446,11 @@ static void mi_option_init(mi_option_desc_t* desc) {
char buf[64+1];
_mi_strlcpy(buf, "mimalloc_", sizeof(buf));
_mi_strlcat(buf, desc->name, sizeof(buf));
- bool found = mi_getenv(buf, s, sizeof(s));
+ bool found = _mi_getenv(buf, s, sizeof(s));
if (!found && desc->legacy_name != NULL) {
_mi_strlcpy(buf, "mimalloc_", sizeof(buf));
_mi_strlcat(buf, desc->legacy_name, sizeof(buf));
- found = mi_getenv(buf, s, sizeof(s));
+ found = _mi_getenv(buf, s, sizeof(s));
if (found) {
_mi_warning_message("environment option \"mimalloc_%s\" is deprecated -- use \"mimalloc_%s\" instead.\n", desc->legacy_name, desc->name);
}
diff --git a/src/prim/unix/prim.c b/src/prim/unix/prim.c
index 314281fe..4ed8bd92 100644
--- a/src/prim/unix/prim.c
+++ b/src/prim/unix/prim.c
@@ -472,8 +472,6 @@ int _mi_prim_alloc_huge_os_pages(void* hint_addr, size_t size, int numa_node, bo
#if defined(__linux__)
-#include // snprintf
-
size_t _mi_prim_numa_node(void) {
#if defined(MI_HAS_SYSCALL_H) && defined(SYS_getcpu)
unsigned long node = 0;
@@ -491,7 +489,7 @@ size_t _mi_prim_numa_node_count(void) {
unsigned node = 0;
for(node = 0; node < 256; node++) {
// enumerate node entries -- todo: it there a more efficient way to do this? (but ensure there is no allocation)
- snprintf(buf, 127, "/sys/devices/system/node/node%u", node + 1);
+ _mi_snprintf(buf, 127, "/sys/devices/system/node/node%u", node + 1);
if (mi_prim_access(buf,R_OK) != 0) break;
}
return (node+1);
diff --git a/src/static.c b/src/static.c
index bc05dd72..bf025eb7 100644
--- a/src/static.c
+++ b/src/static.c
@@ -27,6 +27,7 @@ terms of the MIT license. A copy of the license can be found in the file
#include "bitmap.c"
#include "heap.c"
#include "init.c"
+#include "libc.c"
#include "options.c"
#include "os.c"
#include "page.c" // includes page-queue.c
diff --git a/src/stats.c b/src/stats.c
index 300956ce..1ae5c0ab 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -9,7 +9,6 @@ terms of the MIT license. A copy of the license can be found in the file
#include "mimalloc/atomic.h"
#include "mimalloc/prim.h"
-#include // snprintf
#include // memset
#if defined(_MSC_VER) && (_MSC_VER < 1920)
@@ -146,7 +145,7 @@ static void mi_printf_amount(int64_t n, int64_t unit, mi_output_fun* out, void*
const int64_t pos = (n < 0 ? -n : n);
if (pos < base) {
if (n!=1 || suffix[0] != 'B') { // skip printing 1 B for the unit column
- snprintf(buf, len, "%d %-3s", (int)n, (n==0 ? "" : suffix));
+ _mi_snprintf(buf, len, "%lld %-3s", (long long)n, (n==0 ? "" : suffix));
}
}
else {
@@ -158,8 +157,8 @@ static void mi_printf_amount(int64_t n, int64_t unit, mi_output_fun* out, void*
const long whole = (long)(tens/10);
const long frac1 = (long)(tens%10);
char unitdesc[8];
- snprintf(unitdesc, 8, "%s%s%s", magnitude, (base==1024 ? "i" : ""), suffix);
- snprintf(buf, len, "%ld.%ld %-3s", whole, (frac1 < 0 ? -frac1 : frac1), unitdesc);
+ _mi_snprintf(unitdesc, 8, "%s%s%s", magnitude, (base==1024 ? "i" : ""), suffix);
+ _mi_snprintf(buf, len, "%ld.%ld %-3s", whole, (frac1 < 0 ? -frac1 : frac1), unitdesc);
}
_mi_fprintf(out, arg, (fmt==NULL ? "%12s" : fmt), buf);
}
@@ -255,7 +254,7 @@ static void mi_stats_print_bins(const mi_stat_count_t* bins, size_t max, const c
if (bins[i].allocated > 0) {
found = true;
int64_t unit = _mi_bin_size((uint8_t)i);
- snprintf(buf, 64, "%s %3lu", fmt, (long)i);
+ _mi_snprintf(buf, 64, "%s %3lu", fmt, (long)i);
mi_stat_print(&bins[i], buf, unit, out, arg);
}
}