@@ -167,6 +167,7 @@ void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t me
167167 if (mi_memkind_is_os (memid .memkind )) {
168168 size_t csize = memid .mem .os .size ;
169169 if (csize == 0 ) { csize = _mi_os_good_alloc_size (size ); }
170+ mi_assert_internal (csize >= size );
170171 size_t commit_size = (still_committed ? csize : 0 );
171172 void * base = addr ;
172173 // different base? (due to alignment)
@@ -326,9 +327,11 @@ void* _mi_os_alloc(size_t size, mi_memid_t* memid) {
326327 bool os_is_large = false;
327328 bool os_is_zero = false;
328329 void * p = mi_os_prim_alloc (size , 0 , true, false, & os_is_large , & os_is_zero );
329- if (p != NULL ) {
330- * memid = _mi_memid_create_os (p , size , true, os_is_zero , os_is_large );
331- }
330+ if (p == NULL ) return NULL ;
331+
332+ * memid = _mi_memid_create_os (p , size , true, os_is_zero , os_is_large );
333+ mi_assert_internal (memid -> mem .os .size >= size );
334+ mi_assert_internal (memid -> initially_committed );
332335 return p ;
333336}
334337
@@ -344,14 +347,43 @@ void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allo
344347 bool os_is_zero = false;
345348 void * os_base = NULL ;
346349 void * p = mi_os_prim_alloc_aligned (size , alignment , commit , allow_large , & os_is_large , & os_is_zero , & os_base );
347- if (p != NULL ) {
348- * memid = _mi_memid_create_os (p , size , commit , os_is_zero , os_is_large );
349- memid -> mem .os .base = os_base ;
350- memid -> mem .os .size += ((uint8_t * )p - (uint8_t * )os_base ); // todo: return from prim_alloc_aligned?
350+ if (p == NULL ) return NULL ;
351+
352+ * memid = _mi_memid_create_os (p , size , commit , os_is_zero , os_is_large );
353+ memid -> mem .os .base = os_base ;
354+ memid -> mem .os .size += ((uint8_t * )p - (uint8_t * )os_base ); // todo: return from prim_alloc_aligned?
355+
356+ mi_assert_internal (memid -> mem .os .size >= size );
357+ mi_assert_internal (_mi_is_aligned (p ,alignment ));
358+ if (commit ) { mi_assert_internal (memid -> initially_committed ); }
359+ if (memid -> initially_zero ) { mi_assert_internal (memid -> initially_committed ); }
360+ return p ;
361+ }
362+
363+
364+ mi_decl_nodiscard static void * mi_os_ensure_zero (void * p , size_t size , mi_memid_t * memid ) {
365+ if (p == NULL || size == 0 ) return p ;
366+ // ensure committed
367+ if (!memid -> initially_committed ) {
368+ bool is_zero = false;
369+ if (!_mi_os_commit (p , size , & is_zero )) {
370+ _mi_os_free (p , size , * memid );
371+ return NULL ;
372+ }
373+ memid -> initially_committed = true;
351374 }
375+ // ensure zero'd
376+ if (memid -> initially_zero ) return p ;
377+ _mi_memzero_aligned (p ,size );
378+ memid -> initially_zero = true;
352379 return p ;
353380}
354381
382+ void * _mi_os_zalloc (size_t size , mi_memid_t * memid ) {
383+ void * p = _mi_os_alloc (size ,memid );
384+ return mi_os_ensure_zero (p , size , memid );
385+ }
386+
355387/* -----------------------------------------------------------
356388 OS aligned allocation with an offset. This is used
357389 for large alignments > MI_BLOCK_ALIGNMENT_MAX. We use a large mimalloc
0 commit comments