@@ -266,6 +266,7 @@ struct _zend_mm_heap {
266
266
void * (* _realloc )(void * , size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC );
267
267
} debug ;
268
268
} custom_heap ;
269
+ HashTable * tracked_allocs ;
269
270
#endif
270
271
};
271
272
@@ -2182,20 +2183,32 @@ static void zend_mm_check_leaks(zend_mm_heap *heap)
2182
2183
}
2183
2184
#endif
2184
2185
2186
+ #if ZEND_MM_CUSTOM
2187
+ static void * tracked_malloc (size_t size );
2188
+ static void tracked_free_all ();
2189
+ #endif
2190
+
2185
2191
void zend_mm_shutdown (zend_mm_heap * heap , int full , int silent )
2186
2192
{
2187
2193
zend_mm_chunk * p ;
2188
2194
zend_mm_huge_list * list ;
2189
2195
2190
2196
#if ZEND_MM_CUSTOM
2191
2197
if (heap -> use_custom_heap ) {
2192
- if (full ) {
2193
- if (ZEND_DEBUG && heap -> use_custom_heap == ZEND_MM_CUSTOM_HEAP_DEBUG ) {
2194
- heap -> custom_heap .debug ._free (heap ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC );
2195
- } else {
2196
- heap -> custom_heap .std ._free (heap );
2198
+ if (heap -> custom_heap .std ._malloc == tracked_malloc ) {
2199
+ if (silent ) {
2200
+ tracked_free_all ();
2201
+ }
2202
+ zend_hash_clean (heap -> tracked_allocs );
2203
+ if (full ) {
2204
+ zend_hash_destroy (heap -> tracked_allocs );
2205
+ free (heap -> tracked_allocs );
2197
2206
}
2198
2207
}
2208
+
2209
+ if (full ) {
2210
+ free (heap );
2211
+ }
2199
2212
return ;
2200
2213
}
2201
2214
#endif
@@ -2661,19 +2674,66 @@ ZEND_API void shutdown_memory_manager(int silent, int full_shutdown)
2661
2674
zend_mm_shutdown (AG (mm_heap ), full_shutdown , silent );
2662
2675
}
2663
2676
2677
+ #if ZEND_MM_CUSTOM
2678
+ static void * tracked_malloc (size_t size )
2679
+ {
2680
+ void * ptr = __zend_malloc (size );
2681
+ zend_ulong h = ((uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
2682
+ ZEND_ASSERT ((void * ) (uintptr_t ) (h << ZEND_MM_ALIGNMENT_LOG2 ) == ptr );
2683
+ zend_hash_index_add_empty_element (AG (mm_heap )-> tracked_allocs , h );
2684
+ return ptr ;
2685
+ }
2686
+
2687
+ static void tracked_free (void * ptr ) {
2688
+ zend_ulong h = ((uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
2689
+ zend_hash_index_del (AG (mm_heap )-> tracked_allocs , h );
2690
+ free (ptr );
2691
+ }
2692
+
2693
+ static void * tracked_realloc (void * ptr , size_t new_size ) {
2694
+ zend_ulong h = ((uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
2695
+ zend_hash_index_del (AG (mm_heap )-> tracked_allocs , h );
2696
+ ptr = __zend_realloc (ptr , new_size );
2697
+ h = ((uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
2698
+ ZEND_ASSERT ((void * ) (uintptr_t ) (h << ZEND_MM_ALIGNMENT_LOG2 ) == ptr );
2699
+ zend_hash_index_add_empty_element (AG (mm_heap )-> tracked_allocs , h );
2700
+ return ptr ;
2701
+ }
2702
+
2703
+ static void tracked_free_all () {
2704
+ HashTable * tracked_allocs = AG (mm_heap )-> tracked_allocs ;
2705
+ zend_ulong h ;
2706
+ ZEND_HASH_FOREACH_NUM_KEY (tracked_allocs , h ) {
2707
+ void * ptr = (void * ) (uintptr_t ) (h << ZEND_MM_ALIGNMENT_LOG2 );
2708
+ free (ptr );
2709
+ } ZEND_HASH_FOREACH_END ();
2710
+ }
2711
+ #endif
2712
+
2664
2713
static void alloc_globals_ctor (zend_alloc_globals * alloc_globals )
2665
2714
{
2666
2715
char * tmp ;
2667
2716
2668
2717
#if ZEND_MM_CUSTOM
2669
2718
tmp = getenv ("USE_ZEND_ALLOC" );
2670
2719
if (tmp && !zend_atoi (tmp , 0 )) {
2671
- alloc_globals -> mm_heap = malloc (sizeof (zend_mm_heap ));
2672
- memset (alloc_globals -> mm_heap , 0 , sizeof (zend_mm_heap ));
2673
- alloc_globals -> mm_heap -> use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD ;
2674
- alloc_globals -> mm_heap -> custom_heap .std ._malloc = __zend_malloc ;
2675
- alloc_globals -> mm_heap -> custom_heap .std ._free = free ;
2676
- alloc_globals -> mm_heap -> custom_heap .std ._realloc = __zend_realloc ;
2720
+ zend_bool tracked = (tmp = getenv ("USE_TRACKED_ALLOC" )) && zend_atoi (tmp , 0 );
2721
+ zend_mm_heap * mm_heap = alloc_globals -> mm_heap = malloc (sizeof (zend_mm_heap ));
2722
+ memset (mm_heap , 0 , sizeof (zend_mm_heap ));
2723
+ mm_heap -> use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD ;
2724
+ if (!tracked ) {
2725
+ /* Use system allocator. */
2726
+ mm_heap -> custom_heap .std ._malloc = __zend_malloc ;
2727
+ mm_heap -> custom_heap .std ._free = free ;
2728
+ mm_heap -> custom_heap .std ._realloc = __zend_realloc ;
2729
+ } else {
2730
+ /* Use system allocator and track allocations for auto-free. */
2731
+ mm_heap -> custom_heap .std ._malloc = tracked_malloc ;
2732
+ mm_heap -> custom_heap .std ._free = tracked_free ;
2733
+ mm_heap -> custom_heap .std ._realloc = tracked_realloc ;
2734
+ mm_heap -> tracked_allocs = malloc (sizeof (HashTable ));
2735
+ zend_hash_init (mm_heap -> tracked_allocs , 1024 , NULL , NULL , 1 );
2736
+ }
2677
2737
return ;
2678
2738
}
2679
2739
#endif
0 commit comments