@@ -15,12 +15,21 @@ terms of the MIT license. A copy of the license can be found in the file
15
15
16
16
#if defined(MI_MALLOC_OVERRIDE ) && !(defined(_WIN32 ))
17
17
18
+ #if defined(__APPLE__ )
19
+ mi_decl_externc void vfree (void * p );
20
+ mi_decl_externc size_t malloc_size (const void * p );
21
+ mi_decl_externc size_t malloc_good_size (size_t size );
22
+ #endif
23
+
24
+ // helper definition for C override of C++ new
25
+ typedef struct mi_nothrow_s { int _tag ; } mi_nothrow_t ;
26
+
18
27
// ------------------------------------------------------
19
28
// Override system malloc
20
29
// ------------------------------------------------------
21
30
22
- #if (defined(__GNUC__ ) || defined(__clang__ )) && !defined(__APPLE__ )
23
- // use aliasing to alias the exported function to one of our `mi_` functions
31
+ #if (defined(__GNUC__ ) || defined(__clang__ )) && !defined(__APPLE__ ) && !defined( MI_VALGRIND )
32
+ // gcc, clang: use aliasing to alias the exported function to one of our `mi_` functions
24
33
#if (defined(__GNUC__ ) && __GNUC__ >= 9 )
25
34
#pragma GCC diagnostic ignored "-Wattributes" // or we get warnings that nodiscard is ignored on a forward
26
35
#define MI_FORWARD (fun ) __attribute__((alias(#fun), used, visibility("default"), copy(fun)));
@@ -33,19 +42,18 @@ terms of the MIT license. A copy of the license can be found in the file
33
42
#define MI_FORWARD0 (fun ,x ) MI_FORWARD(fun)
34
43
#define MI_FORWARD02 (fun ,x ,y ) MI_FORWARD(fun)
35
44
#else
36
- // use forwarding by calling our `mi_` function
45
+ // otherwise use forwarding by calling our `mi_` function
37
46
#define MI_FORWARD1 (fun ,x ) { return fun(x); }
38
47
#define MI_FORWARD2 (fun ,x ,y ) { return fun(x,y); }
39
48
#define MI_FORWARD3 (fun ,x ,y ,z ) { return fun(x,y,z); }
40
49
#define MI_FORWARD0 (fun ,x ) { fun(x); }
41
50
#define MI_FORWARD02 (fun ,x ,y ) { fun(x,y); }
42
51
#endif
43
52
44
- #if defined(__APPLE__ ) && defined(MI_SHARED_LIB_EXPORT ) && defined(MI_OSX_INTERPOSE )
45
- #include <malloc/malloc.h>
46
- mi_decl_externc void vfree (void * p );
47
- mi_decl_externc size_t malloc_size (const void * p );
48
- mi_decl_externc size_t malloc_good_size (size_t size );
53
+ #if defined(__APPLE__ ) && defined(MI_SHARED_LIB_EXPORT ) && defined(MI_OSX_INTERPOSE )
54
+ // define MI_OSX_IS_INTERPOSED as we should not provide forwarding definitions for
55
+ // functions that are interposed (or the interposing does not work)
56
+ #define MI_OSX_IS_INTERPOSED
49
57
50
58
// use interposing so `DYLD_INSERT_LIBRARIES` works without `DYLD_FORCE_FLAT_NAMESPACE=1`
51
59
// See: <https://books.google.com/books?id=K8vUkpOXhN4C&pg=PA73>
@@ -70,16 +78,41 @@ terms of the MIT license. A copy of the license can be found in the file
70
78
MI_INTERPOSE_MI (malloc_size ),
71
79
MI_INTERPOSE_MI (malloc_good_size ),
72
80
MI_INTERPOSE_MI (aligned_alloc ),
73
- #ifndef MI_OSX_ZONE
74
- // sometimes code allocates from default zone but deallocates using plain free :-( (like NxHashResizeToCapacity <https://github.com/nneonneo/osx-10.9-opensource/blob/master/objc4-551.1/runtime/hashtable2.mm>)
75
- MI_INTERPOSE_FUN (free ,mi_cfree ), // use safe free that checks if pointers are from us
76
- MI_INTERPOSE_FUN (vfree ,mi_cfree ),
77
- #else
81
+ #ifdef MI_OSX_ZONE
78
82
// we interpose malloc_default_zone in alloc-override-osx.c so we can use mi_free safely
79
83
MI_INTERPOSE_MI (free ),
80
84
MI_INTERPOSE_FUN (vfree ,mi_free ),
85
+ #else
86
+ // sometimes code allocates from default zone but deallocates using plain free :-( (like NxHashResizeToCapacity <https://github.com/nneonneo/osx-10.9-opensource/blob/master/objc4-551.1/runtime/hashtable2.mm>)
87
+ MI_INTERPOSE_FUN (free ,mi_cfree ), // use safe free that checks if pointers are from us
88
+ MI_INTERPOSE_FUN (vfree ,mi_cfree ),
81
89
#endif
82
90
};
91
+
92
+ #ifdef __cplusplus
93
+ extern "C" {
94
+ void _ZdlPv (void * p ); // delete
95
+ void _ZdaPv (void * p ); // delete[]
96
+ void _ZdlPvm (void * p , size_t n ); // delete
97
+ void _ZdaPvm (void * p , size_t n ); // delete[]
98
+ void * _Znwm (size_t n ); // new
99
+ void * _Znam (size_t n ); // new[]
100
+ void * _ZnwmRKSt9nothrow_t (size_t n , mi_nothrow_t tag ); // new nothrow
101
+ void * _ZnamRKSt9nothrow_t (size_t n , mi_nothrow_t tag ); // new[] nothrow
102
+ }
103
+ __attribute__((used )) static struct mi_interpose_s _mi_cxx_interposes [] __attribute__((section ("__DATA, __interpose" ))) =
104
+ {
105
+ MI_INTERPOSE_FUN (_ZdlPv ,mi_free ),
106
+ MI_INTERPOSE_FUN (_ZdaPv ,mi_free ),
107
+ MI_INTERPOSE_FUN (_ZdlPvm ,mi_free_size ),
108
+ MI_INTERPOSE_FUN (_ZdaPvm ,mi_free_size ),
109
+ MI_INTERPOSE_FUN (_Znwm ,mi_new ),
110
+ MI_INTERPOSE_FUN (_Znam ,mi_new ),
111
+ MI_INTERPOSE_FUN (_ZnwmRKSt9nothrow_t ,mi_new_nothrow ),
112
+ MI_INTERPOSE_FUN (_ZnamRKSt9nothrow_t ,mi_new_nothrow ),
113
+ };
114
+ #endif // __cplusplus
115
+
83
116
#elif defined(_MSC_VER)
84
117
// cannot override malloc unless using a dll.
85
118
// we just override new/delete which does work in a static library.
@@ -106,18 +139,21 @@ terms of the MIT license. A copy of the license can be found in the file
106
139
// see <https://en.cppreference.com/w/cpp/memory/new/operator_new>
107
140
// ------------------------------------------------------
108
141
#include <new>
109
- void operator delete (void * p ) noexcept MI_FORWARD0 (mi_free ,p )
110
- void operator delete [](void * p ) noexcept MI_FORWARD0 (mi_free ,p )
111
142
112
- void * operator new (std ::size_t n ) noexcept (false ) MI_FORWARD1 (mi_new ,n )
113
- void * operator new [](std ::size_t n ) noexcept (false ) MI_FORWARD1 (mi_new ,n )
143
+ #ifndef MI_OSX_IS_INTERPOSED
144
+ void operator delete (void * p ) noexcept MI_FORWARD0 (mi_free ,p )
145
+ void operator delete [](void * p ) noexcept MI_FORWARD0 (mi_free ,p )
146
+
147
+ void * operator new (std ::size_t n ) noexcept (false ) MI_FORWARD1 (mi_new ,n )
148
+ void * operator new [](std ::size_t n ) noexcept (false ) MI_FORWARD1 (mi_new ,n )
114
149
115
- void * operator new (std ::size_t n , const std ::nothrow_t & tag ) noexcept { UNUSED (tag ); return mi_new_nothrow (n ); }
116
- void * operator new [](std ::size_t n , const std ::nothrow_t & tag ) noexcept { UNUSED (tag ); return mi_new_nothrow (n ); }
150
+ void * operator new (std ::size_t n , const std ::nothrow_t & tag ) noexcept { UNUSED (tag ); return mi_new_nothrow (n ); }
151
+ void * operator new [](std ::size_t n , const std ::nothrow_t & tag ) noexcept { UNUSED (tag ); return mi_new_nothrow (n ); }
117
152
118
- #if (__cplusplus >= 201402L || _MSC_VER >= 1916 )
119
- void operator delete (void * p , std ::size_t n ) noexcept MI_FORWARD02 (mi_free_size ,p ,n )
120
- void operator delete [](void * p , std ::size_t n ) noexcept MI_FORWARD02 (mi_free_size ,p ,n )
153
+ #if (__cplusplus >= 201402L || _MSC_VER >= 1916 )
154
+ void operator delete (void * p , std ::size_t n ) noexcept MI_FORWARD02 (mi_free_size ,p ,n )
155
+ void operator delete [](void * p , std ::size_t n ) noexcept MI_FORWARD02 (mi_free_size ,p ,n )
156
+ #endif
121
157
#endif
122
158
123
159
#if (__cplusplus > 201402L && defined(__cpp_aligned_new )) && (!defined(__GNUC__ ) || (__GNUC__ > 5 ))
@@ -132,12 +168,13 @@ terms of the MIT license. A copy of the license can be found in the file
132
168
void * operator new [](std ::size_t n , std ::align_val_t al , const std ::nothrow_t & ) noexcept { return mi_new_aligned_nothrow (n , static_cast < size_t > (al )); }
133
169
#endif
134
170
135
- #elif (defined(__GNUC__ ) || defined(__clang__ )) && !defined( MI_OSX_ZONE )
171
+ #elif (defined(__GNUC__ ) || defined(__clang__ ))
136
172
// ------------------------------------------------------
137
173
// Override by defining the mangled C++ names of the operators (as
138
174
// used by GCC and CLang).
139
175
// See <https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling>
140
176
// ------------------------------------------------------
177
+
141
178
void _ZdlPv (void * p ) MI_FORWARD0 (mi_free ,p ) // delete
142
179
void _ZdaPv (void * p ) MI_FORWARD0 (mi_free ,p ) // delete[]
143
180
void _ZdlPvm (void * p , size_t n ) MI_FORWARD02 (mi_free_size ,p ,n )
@@ -146,67 +183,71 @@ terms of the MIT license. A copy of the license can be found in the file
146
183
void _ZdaPvSt11align_val_t (void * p , size_t al ) { mi_free_aligned (p ,al ); }
147
184
void _ZdlPvmSt11align_val_t (void * p , size_t n , size_t al ) { mi_free_size_aligned (p ,n ,al ); }
148
185
void _ZdaPvmSt11align_val_t (void * p , size_t n , size_t al ) { mi_free_size_aligned (p ,n ,al ); }
149
-
150
- typedef struct mi_nothrow_s { int _tag ; } mi_nothrow_t ;
186
+
151
187
#if (MI_INTPTR_SIZE == 8 )
152
188
void * _Znwm (size_t n ) MI_FORWARD1 (mi_new ,n ) // new 64-bit
153
189
void * _Znam (size_t n ) MI_FORWARD1 (mi_new ,n ) // new[] 64-bit
190
+ void * _ZnwmRKSt9nothrow_t (size_t n , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_nothrow (n ); }
191
+ void * _ZnamRKSt9nothrow_t (size_t n , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_nothrow (n ); }
154
192
void * _ZnwmSt11align_val_t (size_t n , size_t al ) MI_FORWARD2 (mi_new_aligned , n , al )
155
193
void * _ZnamSt11align_val_t (size_t n , size_t al ) MI_FORWARD2 (mi_new_aligned , n , al )
156
- void * _ZnwmRKSt9nothrow_t (size_t n , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_nothrow (n ); }
157
- void * _ZnamRKSt9nothrow_t (size_t n , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_nothrow (n ); }
158
194
void * _ZnwmSt11align_val_tRKSt9nothrow_t (size_t n , size_t al , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_aligned_nothrow (n ,al ); }
159
195
void * _ZnamSt11align_val_tRKSt9nothrow_t (size_t n , size_t al , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_aligned_nothrow (n ,al ); }
160
196
#elif (MI_INTPTR_SIZE == 4 )
161
197
void * _Znwj (size_t n ) MI_FORWARD1 (mi_new ,n ) // new 64-bit
162
198
void * _Znaj (size_t n ) MI_FORWARD1 (mi_new ,n ) // new[] 64-bit
199
+ void * _ZnwjRKSt9nothrow_t (size_t n , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_nothrow (n ); }
200
+ void * _ZnajRKSt9nothrow_t (size_t n , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_nothrow (n ); }
163
201
void * _ZnwjSt11align_val_t (size_t n , size_t al ) MI_FORWARD2 (mi_new_aligned , n , al )
164
202
void * _ZnajSt11align_val_t (size_t n , size_t al ) MI_FORWARD2 (mi_new_aligned , n , al )
165
- void * _ZnwjRKSt9nothrow_t (size_t n , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_nothrow (n ); }
166
- void * _ZnajRKSt9nothrow_t (size_t n , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_nothrow (n ); }
167
203
void * _ZnwjSt11align_val_tRKSt9nothrow_t (size_t n , size_t al , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_aligned_nothrow (n ,al ); }
168
204
void * _ZnajSt11align_val_tRKSt9nothrow_t (size_t n , size_t al , mi_nothrow_t tag ) { UNUSED (tag ); return mi_new_aligned_nothrow (n ,al ); }
169
205
#else
170
- #error "define overloads for new/delete for this platform (just for performance, can be skipped)"
206
+ #error "define overloads for new/delete for this platform (just for performance, can be skipped)"
171
207
#endif
172
208
#endif // __cplusplus
173
209
210
+ // ------------------------------------------------------
211
+ // Further Posix & Unix functions definitions
212
+ // ------------------------------------------------------
174
213
175
214
#ifdef __cplusplus
176
215
extern "C" {
177
216
#endif
178
217
179
- // ------------------------------------------------------
180
- // Posix & Unix functions definitions
181
- // ------------------------------------------------------
218
+ #ifndef MI_OSX_IS_INTERPOSED
219
+ // Forward Posix/Unix calls as well
220
+ void * reallocf (void * p , size_t newsize ) MI_FORWARD2 (mi_reallocf ,p ,newsize )
221
+ size_t malloc_size (const void * p ) MI_FORWARD1 (mi_usable_size ,p )
222
+ size_t malloc_good_size (size_t size ) MI_FORWARD1 (mi_malloc_good_size ,size )
223
+ #if !defined(__ANDROID__ ) && !defined(__FreeBSD__ )
224
+ size_t malloc_usable_size (void * p ) MI_FORWARD1 (mi_usable_size ,p )
225
+ #else
226
+ size_t malloc_usable_size (const void * p ) MI_FORWARD1 (mi_usable_size ,p )
227
+ #endif
182
228
183
- void cfree (void * p ) MI_FORWARD0 (mi_free , p )
184
- void * reallocf (void * p , size_t newsize ) MI_FORWARD2 (mi_reallocf ,p ,newsize )
185
- size_t malloc_size (const void * p ) MI_FORWARD1 (mi_usable_size ,p )
186
- #if !defined(__ANDROID__ ) && !defined(__FreeBSD__ )
187
- size_t malloc_usable_size (void * p ) MI_FORWARD1 (mi_usable_size ,p )
188
- #else
189
- size_t malloc_usable_size (const void * p ) MI_FORWARD1 (mi_usable_size ,p )
229
+ // No forwarding here due to aliasing/name mangling issues
230
+ void * valloc (size_t size ) { return mi_valloc (size ); }
231
+ void vfree (void * p ) { mi_free (p ); }
232
+ int posix_memalign (void * * p , size_t alignment , size_t size ) { return mi_posix_memalign (p , alignment , size ); }
233
+
234
+ // `aligned_alloc` is only available when __USE_ISOC11 is defined.
235
+ // Note: Conda has a custom glibc where `aligned_alloc` is declared `static inline` and we cannot
236
+ // override it, but both _ISOC11_SOURCE and __USE_ISOC11 are undefined in Conda GCC7 or GCC9.
237
+ // Fortunately, in the case where `aligned_alloc` is declared as `static inline` it
238
+ // uses internally `memalign`, `posix_memalign`, or `_aligned_malloc` so we can avoid overriding it ourselves.
239
+ #if __USE_ISOC11
240
+ void * aligned_alloc (size_t alignment , size_t size ) { return mi_aligned_alloc (alignment , size ); }
241
+ #endif
190
242
#endif
191
243
192
244
// no forwarding here due to aliasing/name mangling issues
193
- void * valloc ( size_t size ) { return mi_valloc ( size ); }
245
+ void cfree ( void * p ) { mi_free ( p ); }
194
246
void * pvalloc (size_t size ) { return mi_pvalloc (size ); }
195
247
void * reallocarray (void * p , size_t count , size_t size ) { return mi_reallocarray (p , count , size ); }
196
248
void * memalign (size_t alignment , size_t size ) { return mi_memalign (alignment , size ); }
197
- int posix_memalign (void * * p , size_t alignment , size_t size ) { return mi_posix_memalign (p , alignment , size ); }
198
249
void * _aligned_malloc (size_t alignment , size_t size ) { return mi_aligned_alloc (alignment , size ); }
199
250
200
- // `aligned_alloc` is only available when __USE_ISOC11 is defined.
201
- // Note: Conda has a custom glibc where `aligned_alloc` is declared `static inline` and we cannot
202
- // override it, but both _ISOC11_SOURCE and __USE_ISOC11 are undefined in Conda GCC7 or GCC9.
203
- // Fortunately, in the case where `aligned_alloc` is declared as `static inline` it
204
- // uses internally `memalign`, `posix_memalign`, or `_aligned_malloc` so we can avoid overriding it ourselves.
205
- #if __USE_ISOC11
206
- void * aligned_alloc (size_t alignment , size_t size ) { return mi_aligned_alloc (alignment , size ); }
207
- #endif
208
-
209
-
210
251
#if defined(__GLIBC__ ) && defined(__linux__ )
211
252
// forward __libc interface (needed for glibc-based Linux distributions)
212
253
void * __libc_malloc (size_t size ) MI_FORWARD1 (mi_malloc ,size )
0 commit comments