diff --git a/src/alloc-override-win.c b/src/alloc-override-win.c index 56f8d149..93886982 100644 --- a/src/alloc-override-win.c +++ b/src/alloc-override-win.c @@ -15,6 +15,9 @@ terms of the MIT license. A copy of the license can be found in the file #include #include +#include // getenv +#include // strstr + /* To override the C runtime `malloc` on Windows we need to patch the allocation @@ -143,12 +146,6 @@ static size_t mi__msize_term(void* p) { } -// Debug versions, forward to base versions in ucrtbase (that get patched) -void* _malloc_base(size_t size); -void* _calloc_base(size_t size, size_t count); -void* _realloc_base(void* p, size_t new_size); -void _free_base(void* p); - static void* mi__malloc_dbg(size_t size, int block_type, const char* fname, int line) { UNUSED(block_type); UNUSED(fname); UNUSED(line); return _malloc_base(size); @@ -578,7 +575,7 @@ static void mi_module_resolve(const char* fname, HMODULE mod, int priority) { if (addr != NULL) { // found it! set the address patch->originals[i] = addr; - _mi_trace_message(" override %s at %s!%p (entry %i)\n", patch->name, fname, addr, i); + _mi_trace_message(" found %s at %s!%p (entry %i)\n", patch->name, fname, addr, i); } } } @@ -605,7 +602,6 @@ static bool mi_patches_resolve(void) { int ucrtbase_index = 0; int mimalloc_index = 0; // iterate through the loaded modules - _mi_trace_message("overriding malloc dynamically...\n"); for (int i = 0; i < count; i++) { HMODULE mod = modules[i]; char filename[MAX_PATH] = { 0 }; @@ -679,27 +675,39 @@ __declspec(dllexport) BOOL WINAPI DllEntry(HINSTANCE inst, DWORD reason, LPVOID mi_patches_enable_term(); } // C runtime main - BOOL ok = _DllMainCRTStartup(inst, reason, reserved); + BOOL ok = _DllMainCRTStartup(inst, reason, reserved); if (reason == DLL_PROCESS_ATTACH && ok) { + // initialize at exit lists + mi_initialize_atexit(); + // Now resolve patches ok = mi_patches_resolve(); if (ok) { - // and register our unwind entry (this must be after resolving due to possible delayed DLL initialization from GetProcAddress) - mi_fls_unwind_entry = FlsAlloc(&mi_fls_unwind); - if (mi_fls_unwind_entry != FLS_OUT_OF_INDEXES) { - FlsSetValue(mi_fls_unwind_entry, (void*)1); + // check if patching is not disabled + #pragma warning(suppress:4996) + const char* s = getenv("MIMALLOC_OVERRIDE"); + bool enabled = (s == NULL || strstr("1;TRUE;YES;ON", s) != NULL); + if (!enabled) { + _mi_verbose_message("override is disabled\n"); } + else { + // and register our unwind entry (this must be after resolving due to possible delayed DLL initialization from GetProcAddress) + mi_fls_unwind_entry = FlsAlloc(&mi_fls_unwind); + if (mi_fls_unwind_entry != FLS_OUT_OF_INDEXES) { + FlsSetValue(mi_fls_unwind_entry, (void*)1); + } - // register our patch disabler in the global exit list - mi_initialize_atexit(); - if (crt_atexit != NULL) (*crt_atexit)(&mi_patches_atexit); - if (crt_at_quick_exit != NULL) (*crt_at_quick_exit)(&mi_patches_at_quick_exit); + // register our patch disabler in the global exit list + if (crt_atexit != NULL) (*crt_atexit)(&mi_patches_atexit); + if (crt_at_quick_exit != NULL) (*crt_at_quick_exit)(&mi_patches_at_quick_exit); - // and patch ! this also redirects the `atexit` handling for the global exit list - mi_patches_enable(); + // and patch ! this also redirects the `atexit` handling for the global exit list + mi_patches_enable(); + _mi_verbose_message("override is enabled\n"); - // hide internal allocation - mi_stats_reset(); + // hide internal allocation + mi_stats_reset(); + } } } return ok; diff --git a/src/init.c b/src/init.c index c202eb2b..8075ea35 100644 --- a/src/init.c +++ b/src/init.c @@ -385,7 +385,7 @@ bool _mi_preloading() { } // Communicate with the redirection module on Windows -#if defined(_WIN32) && defined(XMI_SHARED_LIB) +#if 0 #ifdef __cplusplus extern "C" { #endif diff --git a/src/options.c b/src/options.c index a68ddbdf..01620e75 100644 --- a/src/options.c +++ b/src/options.c @@ -60,7 +60,7 @@ static mi_option_desc_t options[_mi_option_last] = { 0, UNINIT, "large_os_pages" }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's { 0, UNINIT, "page_reset" }, { 0, UNINIT, "cache_reset" }, - { 0, UNINIT, "reset_decommits" }, // note: cannot enable this if secure is on + { 0, UNINIT, "reset_decommits" }, // note: cannot enable this if secure is on { 0, UNINIT, "reset_discards" } // note: cannot enable this if secure is on }; @@ -213,12 +213,13 @@ static const char* mi_getenv(const char* name) { #pragma warning(suppress:4996) const char* s = getenv(name); if (s == NULL) { - char buf[64]; - mi_strlcpy(buf,name,sizeof(buf)); - size_t buf_size = strlen(buf); - for (size_t i = 0; i < buf_size; i++) { - buf[i] = toupper(buf[i]); + char buf[64+1]; + size_t len = strlen(name); + if (len >= sizeof(buf)) len = sizeof(buf) - 1; + for (size_t i = 0; i < len; i++) { + buf[i] = toupper(name[i]); } + buf[len] = 0; #pragma warning(suppress:4996) s = getenv(buf); } @@ -228,16 +229,17 @@ static const char* mi_getenv(const char* name) { static void mi_option_init(mi_option_desc_t* desc) { if (!_mi_preloading()) desc->init = DEFAULTED; // Read option value from the environment - char buf[64]; + char buf[64+1]; mi_strlcpy(buf, "mimalloc_", sizeof(buf)); mi_strlcat(buf, desc->name, sizeof(buf)); - const char* s = mi_getenv(buf); + const char* s = mi_getenv(buf); if (s != NULL) { - mi_strlcpy(buf, s, sizeof(buf)); - size_t buf_size = strlen(buf); // TODO: use strnlen? - for (size_t i = 0; i < buf_size; i++) { - buf[i] = toupper(buf[i]); + size_t len = strlen(s); + if (len >= sizeof(buf)) len = sizeof(buf) - 1; + for (size_t i = 0; i < len; i++) { + buf[i] = toupper(s[i]); } + buf[len] = 0; if (buf[0]==0 || strstr("1;TRUE;YES;ON", buf) != NULL) { desc->value = 1; desc->init = INITIALIZED; diff --git a/src/os.c b/src/os.c index 56abd55d..b0eab87d 100644 --- a/src/os.c +++ b/src/os.c @@ -204,7 +204,7 @@ static void* mi_win_virtual_alloc(void* addr, size_t size, size_t try_alignment, if (use_large_os_page(size, try_alignment)) { uintptr_t try_ok = mi_atomic_read(&large_page_try_ok); if (try_ok > 0) { - // if a large page page allocation fails, it seems the calls to VirtualAlloc get very expensive. + // if a large page allocation fails, it seems the calls to VirtualAlloc get very expensive. // therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times. mi_atomic_compare_exchange(&large_page_try_ok, try_ok - 1, try_ok); } diff --git a/test/main-override.cpp b/test/main-override.cpp index 6c7fc0d5..58d06c6a 100644 --- a/test/main-override.cpp +++ b/test/main-override.cpp @@ -30,12 +30,12 @@ int main() { free(p1); p1 = malloc(8); char* s = mi_strdup("hello\n"); - free(p2); + mi_free(p2); p2 = malloc(16); p1 = realloc(p1, 32); free(p1); free(p2); - free(s); + mi_free(s); Test* t = new Test(42); delete t; t = new (std::nothrow) Test(42);