@@ -19,12 +19,12 @@ const mi_page_t _mi_page_empty = {
19
19
false, // is_zero
20
20
0 , // retire_expire
21
21
NULL , // free
22
- #if MI_ENCODE_FREELIST
23
- { 0 , 0 },
24
- #endif
25
22
0 , // used
26
23
0 , // xblock_size
27
24
NULL , // local_free
25
+ #if MI_ENCODE_FREELIST
26
+ { 0 , 0 },
27
+ #endif
28
28
MI_ATOMIC_VAR_INIT (0 ), // xthread_free
29
29
MI_ATOMIC_VAR_INIT (0 ), // xheap
30
30
NULL , NULL
@@ -109,8 +109,9 @@ mi_decl_cache_align const mi_heap_t _mi_heap_empty = {
109
109
MI_ATOMIC_VAR_INIT (NULL ),
110
110
0 , // tid
111
111
0 , // cookie
112
+ 0 , // arena id
112
113
{ 0 , 0 }, // keys
113
- { {0 }, {0 }, 0 },
114
+ { {0 }, {0 }, 0 , true }, // random
114
115
0 , // page count
115
116
MI_BIN_FULL , 0 , // page retired min/max
116
117
NULL , // next
@@ -149,8 +150,9 @@ mi_heap_t _mi_heap_main = {
149
150
MI_ATOMIC_VAR_INIT (NULL ),
150
151
0 , // thread id
151
152
0 , // initial cookie
153
+ 0 , // arena id
152
154
{ 0 , 0 }, // the key of the main heap can be fixed (unlike page keys that need to be secure!)
153
- { {0x846ca68b }, {0 }, 0 }, // random
155
+ { {0x846ca68b }, {0 }, 0 , true }, // random
154
156
0 , // page count
155
157
MI_BIN_FULL , 0 , // page retired min/max
156
158
NULL , // next heap
@@ -165,8 +167,13 @@ mi_stats_t _mi_stats_main = { MI_STATS_NULL };
165
167
static void mi_heap_main_init (void ) {
166
168
if (_mi_heap_main .cookie == 0 ) {
167
169
_mi_heap_main .thread_id = _mi_thread_id ();
168
- _mi_heap_main .cookie = _mi_os_random_weak ((uintptr_t )& mi_heap_main_init );
169
- _mi_random_init (& _mi_heap_main .random );
170
+ _mi_heap_main .cookie = 1 ;
171
+ #if defined(_WIN32 ) && !defined(MI_SHARED_LIB )
172
+ _mi_random_init_weak (& _mi_heap_main .random ); // prevent allocation failure during bcrypt dll initialization with static linking
173
+ #else
174
+ _mi_random_init (& _mi_heap_main .random );
175
+ #endif
176
+ _mi_heap_main .cookie = _mi_heap_random_next (& _mi_heap_main );
170
177
_mi_heap_main .keys [0 ] = _mi_heap_random_next (& _mi_heap_main );
171
178
_mi_heap_main .keys [1 ] = _mi_heap_random_next (& _mi_heap_main );
172
179
}
@@ -372,7 +379,11 @@ static void _mi_thread_done(mi_heap_t* default_heap);
372
379
#endif
373
380
static DWORD mi_fls_key = (DWORD )(-1 );
374
381
static void NTAPI mi_fls_done (PVOID value ) {
375
- if (value != NULL ) _mi_thread_done ((mi_heap_t * )value );
382
+ mi_heap_t * heap = (mi_heap_t * )value ;
383
+ if (heap != NULL ) {
384
+ _mi_thread_done (heap );
385
+ FlsSetValue (mi_fls_key , NULL ); // prevent recursion as _mi_thread_done may set it back to the main heap, issue #672
386
+ }
376
387
}
377
388
#elif defined(MI_USE_PTHREADS )
378
389
// use pthread local storage keys to detect thread ending
@@ -475,7 +486,7 @@ void _mi_heap_set_default_direct(mi_heap_t* heap) {
475
486
// --------------------------------------------------------
476
487
// Run functions on process init/done, and thread init/done
477
488
// --------------------------------------------------------
478
- static void mi_process_done (void );
489
+ static void mi_cdecl mi_process_done (void );
479
490
480
491
static bool os_preloading = true; // true until this module is initialized
481
492
static bool mi_redirected = false; // true if malloc redirects to mi_malloc
@@ -490,7 +501,7 @@ mi_decl_nodiscard bool mi_is_redirected(void) mi_attr_noexcept {
490
501
}
491
502
492
503
// Communicate with the redirection module on Windows
493
- #if defined(_WIN32 ) && defined(MI_SHARED_LIB )
504
+ #if defined(_WIN32 ) && defined(MI_SHARED_LIB ) && !defined( MI_WIN_NOREDIRECT )
494
505
#ifdef __cplusplus
495
506
extern "C" {
496
507
#endif
@@ -506,8 +517,8 @@ mi_decl_export void _mi_redirect_entry(DWORD reason) {
506
517
mi_thread_done ();
507
518
}
508
519
}
509
- __declspec(dllimport ) bool mi_allocator_init (const char * * message );
510
- __declspec(dllimport ) void mi_allocator_done (void );
520
+ __declspec(dllimport ) bool mi_cdecl mi_allocator_init (const char * * message );
521
+ __declspec(dllimport ) void mi_cdecl mi_allocator_done (void );
511
522
#ifdef __cplusplus
512
523
}
513
524
#endif
@@ -529,12 +540,13 @@ static void mi_process_load(void) {
529
540
MI_UNUSED (dummy );
530
541
#endif
531
542
os_preloading = false;
543
+ mi_assert_internal (_mi_is_main_thread ());
532
544
#if !(defined(_WIN32 ) && defined(MI_SHARED_LIB )) // use Dll process detach (see below) instead of atexit (issue #521)
533
545
atexit (& mi_process_done );
534
546
#endif
535
547
_mi_options_init ();
548
+ mi_process_setup_auto_thread_done ();
536
549
mi_process_init ();
537
- //mi_stats_reset();-
538
550
if (mi_redirected ) _mi_verbose_message ("malloc is redirected.\n" );
539
551
540
552
// show message from the redirector (if present)
@@ -543,6 +555,9 @@ static void mi_process_load(void) {
543
555
if (msg != NULL && (mi_option_is_enabled (mi_option_verbose ) || mi_option_is_enabled (mi_option_show_errors ))) {
544
556
_mi_fputs (NULL ,NULL ,NULL ,msg );
545
557
}
558
+
559
+ // reseed random
560
+ _mi_random_reinit_if_weak (& _mi_heap_main .random );
546
561
}
547
562
548
563
#if defined(_WIN32 ) && (defined(_M_IX86 ) || defined(_M_X64 ))
@@ -569,14 +584,14 @@ void mi_process_init(void) mi_attr_noexcept {
569
584
_mi_process_is_initialized = true;
570
585
mi_process_setup_auto_thread_done ();
571
586
572
-
573
587
mi_detect_cpu_features ();
574
588
_mi_os_init ();
575
589
mi_heap_main_init ();
576
590
#if (MI_DEBUG )
577
591
_mi_verbose_message ("debug level : %d\n" , MI_DEBUG );
578
592
#endif
579
593
_mi_verbose_message ("secure level: %d\n" , MI_SECURE );
594
+ _mi_verbose_message ("mem tracking: %s\n" , MI_TRACK_TOOL );
580
595
mi_thread_init ();
581
596
582
597
#if defined(_WIN32 ) && !defined(MI_SHARED_LIB )
@@ -606,7 +621,7 @@ void mi_process_init(void) mi_attr_noexcept {
606
621
}
607
622
608
623
// Called when the process is done (through `at_exit`)
609
- static void mi_process_done (void ) {
624
+ static void mi_cdecl mi_process_done (void ) {
610
625
// only shutdown if we were initialized
611
626
if (!_mi_process_is_initialized ) return ;
612
627
// ensure we are called once
@@ -627,6 +642,14 @@ static void mi_process_done(void) {
627
642
#endif
628
643
#endif
629
644
645
+ // Forcefully release all retained memory; this can be dangerous in general if overriding regular malloc/free
646
+ // since after process_done there might still be other code running that calls `free` (like at_exit routines,
647
+ // or C-runtime termination code.
648
+ if (mi_option_is_enabled (mi_option_destroy_on_exit )) {
649
+ _mi_heap_destroy_all (); // forcefully release all memory held by all heaps (of this thread only!)
650
+ _mi_segment_cache_free_all (& _mi_heap_main_get ()-> tld -> os ); // release all cached segments
651
+ }
652
+
630
653
if (mi_option_is_enabled (mi_option_show_stats ) || mi_option_is_enabled (mi_option_verbose )) {
631
654
mi_stats_print (NULL );
632
655
}
0 commit comments