1 | /* ---------------------------------------------------------------------------- |
2 | Copyright (c) 2018-2020, Microsoft Research, Daan Leijen |
3 | This is free software; you can redistribute it and/or modify it under the |
4 | terms of the MIT license. A copy of the license can be found in the file |
5 | "LICENSE" at the root of this distribution. |
6 | -----------------------------------------------------------------------------*/ |
7 | #include "mimalloc.h" |
8 | #include "mimalloc-types.h" |
9 | |
10 | #include "testhelper.h" |
11 | |
12 | // --------------------------------------------------------------------------- |
13 | // Helper functions |
14 | // --------------------------------------------------------------------------- |
15 | bool check_zero_init(uint8_t* p, size_t size); |
16 | #if MI_DEBUG >= 2 |
17 | bool check_debug_fill_uninit(uint8_t* p, size_t size); |
18 | bool check_debug_fill_freed(uint8_t* p, size_t size); |
19 | #endif |
20 | |
21 | // --------------------------------------------------------------------------- |
22 | // Main testing |
23 | // --------------------------------------------------------------------------- |
24 | int main(void) { |
25 | mi_option_disable(mi_option_verbose); |
26 | |
27 | // --------------------------------------------------- |
28 | // Zeroing allocation |
29 | // --------------------------------------------------- |
30 | CHECK_BODY("zeroinit-zalloc-small" ) { |
31 | size_t zalloc_size = MI_SMALL_SIZE_MAX / 2; |
32 | uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size); |
33 | result = check_zero_init(p, zalloc_size); |
34 | mi_free(p); |
35 | }; |
36 | CHECK_BODY("zeroinit-zalloc-large" ) { |
37 | size_t zalloc_size = MI_SMALL_SIZE_MAX * 2; |
38 | uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size); |
39 | result = check_zero_init(p, zalloc_size); |
40 | mi_free(p); |
41 | }; |
42 | CHECK_BODY("zeroinit-zalloc_small" ) { |
43 | size_t zalloc_size = MI_SMALL_SIZE_MAX / 2; |
44 | uint8_t* p = (uint8_t*)mi_zalloc_small(zalloc_size); |
45 | result = check_zero_init(p, zalloc_size); |
46 | mi_free(p); |
47 | }; |
48 | |
49 | CHECK_BODY("zeroinit-calloc-small" ) { |
50 | size_t calloc_size = MI_SMALL_SIZE_MAX / 2; |
51 | uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1); |
52 | result = check_zero_init(p, calloc_size); |
53 | mi_free(p); |
54 | }; |
55 | CHECK_BODY("zeroinit-calloc-large" ) { |
56 | size_t calloc_size = MI_SMALL_SIZE_MAX * 2; |
57 | uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1); |
58 | result = check_zero_init(p, calloc_size); |
59 | mi_free(p); |
60 | }; |
61 | |
62 | CHECK_BODY("zeroinit-rezalloc-small" ) { |
63 | size_t zalloc_size = MI_SMALL_SIZE_MAX / 2; |
64 | uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size); |
65 | result = check_zero_init(p, zalloc_size); |
66 | zalloc_size *= 3; |
67 | p = (uint8_t*)mi_rezalloc(p, zalloc_size); |
68 | result &= check_zero_init(p, zalloc_size); |
69 | mi_free(p); |
70 | }; |
71 | CHECK_BODY("zeroinit-rezalloc-large" ) { |
72 | size_t zalloc_size = MI_SMALL_SIZE_MAX * 2; |
73 | uint8_t* p = (uint8_t*)mi_zalloc(zalloc_size); |
74 | result = check_zero_init(p, zalloc_size); |
75 | zalloc_size *= 3; |
76 | p = (uint8_t*)mi_rezalloc(p, zalloc_size); |
77 | result &= check_zero_init(p, zalloc_size); |
78 | mi_free(p); |
79 | }; |
80 | |
81 | CHECK_BODY("zeroinit-recalloc-small" ) { |
82 | size_t calloc_size = MI_SMALL_SIZE_MAX / 2; |
83 | uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1); |
84 | result = check_zero_init(p, calloc_size); |
85 | calloc_size *= 3; |
86 | p = (uint8_t*)mi_recalloc(p, calloc_size, 1); |
87 | result &= check_zero_init(p, calloc_size); |
88 | mi_free(p); |
89 | }; |
90 | CHECK_BODY("zeroinit-recalloc-large" ) { |
91 | size_t calloc_size = MI_SMALL_SIZE_MAX * 2; |
92 | uint8_t* p = (uint8_t*)mi_calloc(calloc_size, 1); |
93 | result = check_zero_init(p, calloc_size); |
94 | calloc_size *= 3; |
95 | p = (uint8_t*)mi_recalloc(p, calloc_size, 1); |
96 | result &= check_zero_init(p, calloc_size); |
97 | mi_free(p); |
98 | }; |
99 | |
100 | // --------------------------------------------------- |
101 | // Zeroing in aligned API |
102 | // --------------------------------------------------- |
103 | CHECK_BODY("zeroinit-zalloc_aligned-small" ) { |
104 | size_t zalloc_size = MI_SMALL_SIZE_MAX / 2; |
105 | uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2); |
106 | result = check_zero_init(p, zalloc_size); |
107 | mi_free(p); |
108 | }; |
109 | CHECK_BODY("zeroinit-zalloc_aligned-large" ) { |
110 | size_t zalloc_size = MI_SMALL_SIZE_MAX * 2; |
111 | uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2); |
112 | result = check_zero_init(p, zalloc_size); |
113 | mi_free(p); |
114 | }; |
115 | |
116 | CHECK_BODY("zeroinit-calloc_aligned-small" ) { |
117 | size_t calloc_size = MI_SMALL_SIZE_MAX / 2; |
118 | uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2); |
119 | result = check_zero_init(p, calloc_size); |
120 | mi_free(p); |
121 | }; |
122 | CHECK_BODY("zeroinit-calloc_aligned-large" ) { |
123 | size_t calloc_size = MI_SMALL_SIZE_MAX * 2; |
124 | uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2); |
125 | result = check_zero_init(p, calloc_size); |
126 | mi_free(p); |
127 | }; |
128 | |
129 | CHECK_BODY("zeroinit-rezalloc_aligned-small" ) { |
130 | size_t zalloc_size = MI_SMALL_SIZE_MAX / 2; |
131 | uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2); |
132 | result = check_zero_init(p, zalloc_size); |
133 | zalloc_size *= 3; |
134 | p = (uint8_t*)mi_rezalloc_aligned(p, zalloc_size, MI_MAX_ALIGN_SIZE * 2); |
135 | result &= check_zero_init(p, zalloc_size); |
136 | mi_free(p); |
137 | }; |
138 | CHECK_BODY("zeroinit-rezalloc_aligned-large" ) { |
139 | size_t zalloc_size = MI_SMALL_SIZE_MAX * 2; |
140 | uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2); |
141 | result = check_zero_init(p, zalloc_size); |
142 | zalloc_size *= 3; |
143 | p = (uint8_t*)mi_rezalloc_aligned(p, zalloc_size, MI_MAX_ALIGN_SIZE * 2); |
144 | result &= check_zero_init(p, zalloc_size); |
145 | mi_free(p); |
146 | }; |
147 | |
148 | CHECK_BODY("zeroinit-recalloc_aligned-small" ) { |
149 | size_t calloc_size = MI_SMALL_SIZE_MAX / 2; |
150 | uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2); |
151 | result = check_zero_init(p, calloc_size); |
152 | calloc_size *= 3; |
153 | p = (uint8_t*)mi_recalloc_aligned(p, calloc_size, 1, MI_MAX_ALIGN_SIZE * 2); |
154 | result &= check_zero_init(p, calloc_size); |
155 | mi_free(p); |
156 | }; |
157 | CHECK_BODY("zeroinit-recalloc_aligned-large" ) { |
158 | size_t calloc_size = MI_SMALL_SIZE_MAX * 2; |
159 | uint8_t* p = (uint8_t*)mi_calloc_aligned(calloc_size, 1, MI_MAX_ALIGN_SIZE * 2); |
160 | result = check_zero_init(p, calloc_size); |
161 | calloc_size *= 3; |
162 | p = (uint8_t*)mi_recalloc_aligned(p, calloc_size, 1, MI_MAX_ALIGN_SIZE * 2); |
163 | result &= check_zero_init(p, calloc_size); |
164 | mi_free(p); |
165 | }; |
166 | |
167 | #if MI_DEBUG >= 2 |
168 | // --------------------------------------------------- |
169 | // Debug filling |
170 | // --------------------------------------------------- |
171 | CHECK_BODY("uninit-malloc-small" ) { |
172 | size_t malloc_size = MI_SMALL_SIZE_MAX / 2; |
173 | uint8_t* p = (uint8_t*)mi_malloc(malloc_size); |
174 | result = check_debug_fill_uninit(p, malloc_size); |
175 | mi_free(p); |
176 | }; |
177 | CHECK_BODY("uninit-malloc-large" ) { |
178 | size_t malloc_size = MI_SMALL_SIZE_MAX * 2; |
179 | uint8_t* p = (uint8_t*)mi_malloc(malloc_size); |
180 | result = check_debug_fill_uninit(p, malloc_size); |
181 | mi_free(p); |
182 | }; |
183 | |
184 | CHECK_BODY("uninit-malloc_small" ) { |
185 | size_t malloc_size = MI_SMALL_SIZE_MAX / 2; |
186 | uint8_t* p = (uint8_t*)mi_malloc_small(malloc_size); |
187 | result = check_debug_fill_uninit(p, malloc_size); |
188 | mi_free(p); |
189 | }; |
190 | |
191 | CHECK_BODY("uninit-realloc-small" ) { |
192 | size_t malloc_size = MI_SMALL_SIZE_MAX / 2; |
193 | uint8_t* p = (uint8_t*)mi_malloc(malloc_size); |
194 | result = check_debug_fill_uninit(p, malloc_size); |
195 | malloc_size *= 3; |
196 | p = (uint8_t*)mi_realloc(p, malloc_size); |
197 | result &= check_debug_fill_uninit(p, malloc_size); |
198 | mi_free(p); |
199 | }; |
200 | CHECK_BODY("uninit-realloc-large" ) { |
201 | size_t malloc_size = MI_SMALL_SIZE_MAX * 2; |
202 | uint8_t* p = (uint8_t*)mi_malloc(malloc_size); |
203 | result = check_debug_fill_uninit(p, malloc_size); |
204 | malloc_size *= 3; |
205 | p = (uint8_t*)mi_realloc(p, malloc_size); |
206 | result &= check_debug_fill_uninit(p, malloc_size); |
207 | mi_free(p); |
208 | }; |
209 | |
210 | CHECK_BODY("uninit-mallocn-small" ) { |
211 | size_t malloc_size = MI_SMALL_SIZE_MAX / 2; |
212 | uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1); |
213 | result = check_debug_fill_uninit(p, malloc_size); |
214 | mi_free(p); |
215 | }; |
216 | CHECK_BODY("uninit-mallocn-large" ) { |
217 | size_t malloc_size = MI_SMALL_SIZE_MAX * 2; |
218 | uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1); |
219 | result = check_debug_fill_uninit(p, malloc_size); |
220 | mi_free(p); |
221 | }; |
222 | |
223 | CHECK_BODY("uninit-reallocn-small" ) { |
224 | size_t malloc_size = MI_SMALL_SIZE_MAX / 2; |
225 | uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1); |
226 | result = check_debug_fill_uninit(p, malloc_size); |
227 | malloc_size *= 3; |
228 | p = (uint8_t*)mi_reallocn(p, malloc_size, 1); |
229 | result &= check_debug_fill_uninit(p, malloc_size); |
230 | mi_free(p); |
231 | }; |
232 | CHECK_BODY("uninit-reallocn-large" ) { |
233 | size_t malloc_size = MI_SMALL_SIZE_MAX * 2; |
234 | uint8_t* p = (uint8_t*)mi_mallocn(malloc_size, 1); |
235 | result = check_debug_fill_uninit(p, malloc_size); |
236 | malloc_size *= 3; |
237 | p = (uint8_t*)mi_reallocn(p, malloc_size, 1); |
238 | result &= check_debug_fill_uninit(p, malloc_size); |
239 | mi_free(p); |
240 | }; |
241 | |
242 | CHECK_BODY("uninit-malloc_aligned-small" ) { |
243 | size_t malloc_size = MI_SMALL_SIZE_MAX / 2; |
244 | uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2); |
245 | result = check_debug_fill_uninit(p, malloc_size); |
246 | mi_free(p); |
247 | }; |
248 | CHECK_BODY("uninit-malloc_aligned-large" ) { |
249 | size_t malloc_size = MI_SMALL_SIZE_MAX * 2; |
250 | uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2); |
251 | result = check_debug_fill_uninit(p, malloc_size); |
252 | mi_free(p); |
253 | }; |
254 | |
255 | CHECK_BODY("uninit-realloc_aligned-small" ) { |
256 | size_t malloc_size = MI_SMALL_SIZE_MAX / 2; |
257 | uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2); |
258 | result = check_debug_fill_uninit(p, malloc_size); |
259 | malloc_size *= 3; |
260 | p = (uint8_t*)mi_realloc_aligned(p, malloc_size, MI_MAX_ALIGN_SIZE * 2); |
261 | result &= check_debug_fill_uninit(p, malloc_size); |
262 | mi_free(p); |
263 | }; |
264 | CHECK_BODY("uninit-realloc_aligned-large" ) { |
265 | size_t malloc_size = MI_SMALL_SIZE_MAX * 2; |
266 | uint8_t* p = (uint8_t*)mi_malloc_aligned(malloc_size, MI_MAX_ALIGN_SIZE * 2); |
267 | result = check_debug_fill_uninit(p, malloc_size); |
268 | malloc_size *= 3; |
269 | p = (uint8_t*)mi_realloc_aligned(p, malloc_size, MI_MAX_ALIGN_SIZE * 2); |
270 | result &= check_debug_fill_uninit(p, malloc_size); |
271 | mi_free(p); |
272 | }; |
273 | |
274 | |
275 | CHECK_BODY("fill-freed-small" ) { |
276 | size_t malloc_size = MI_SMALL_SIZE_MAX / 2; |
277 | uint8_t* p = (uint8_t*)mi_malloc(malloc_size); |
278 | mi_free(p); |
279 | // First sizeof(void*) bytes will contain housekeeping data, skip these |
280 | result = check_debug_fill_freed(p + sizeof(void*), malloc_size - sizeof(void*)); |
281 | }; |
282 | CHECK_BODY("fill-freed-large" ) { |
283 | size_t malloc_size = MI_SMALL_SIZE_MAX * 2; |
284 | uint8_t* p = (uint8_t*)mi_malloc(malloc_size); |
285 | mi_free(p); |
286 | // First sizeof(void*) bytes will contain housekeeping data, skip these |
287 | result = check_debug_fill_freed(p + sizeof(void*), malloc_size - sizeof(void*)); |
288 | }; |
289 | #endif |
290 | |
291 | // --------------------------------------------------- |
292 | // Done |
293 | // ---------------------------------------------------[] |
294 | return print_test_summary(); |
295 | } |
296 | |
297 | // --------------------------------------------------------------------------- |
298 | // Helper functions |
299 | // --------------------------------------------------------------------------- |
300 | bool check_zero_init(uint8_t* p, size_t size) { |
301 | if(!p) |
302 | return false; |
303 | bool result = true; |
304 | for (size_t i = 0; i < size; ++i) { |
305 | result &= p[i] == 0; |
306 | } |
307 | return result; |
308 | } |
309 | |
310 | #if MI_DEBUG >= 2 |
311 | bool check_debug_fill_uninit(uint8_t* p, size_t size) { |
312 | #if MI_VALGRIND |
313 | (void)p; (void)size; |
314 | return true; // when compiled with valgrind we don't init on purpose |
315 | #else |
316 | if(!p) |
317 | return false; |
318 | |
319 | bool result = true; |
320 | for (size_t i = 0; i < size; ++i) { |
321 | result &= p[i] == MI_DEBUG_UNINIT; |
322 | } |
323 | return result; |
324 | #endif |
325 | } |
326 | |
327 | bool check_debug_fill_freed(uint8_t* p, size_t size) { |
328 | #if MI_VALGRIND |
329 | (void)p; (void)size; |
330 | return true; // when compiled with valgrind we don't fill on purpose |
331 | #else |
332 | if(!p) |
333 | return false; |
334 | |
335 | bool result = true; |
336 | for (size_t i = 0; i < size; ++i) { |
337 | result &= p[i] == MI_DEBUG_FREED; |
338 | } |
339 | return result; |
340 | #endif |
341 | } |
342 | #endif |
343 | |