#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic ignored "-Walloc-size-larger-than="
#endif
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <errno.h>
#ifdef __cplusplus
#include <vector>
#endif
#include "mimalloc.h"
#include "mimalloc/types.h"
#include "testhelper.h"
bool test_theap1(void);
bool test_theap2(void);
bool test_theap_arena_destroy(void);
bool test_theap_arena_delete(void);
bool test_stl_allocator1(void);
bool test_stl_allocator2(void);
bool test_stl_theap_allocator1(void);
bool test_stl_theap_allocator2(void);
bool test_stl_theap_allocator3(void);
bool test_stl_theap_allocator4(void);
bool mem_is_zero(uint8_t* p, size_t size) {
if (p==NULL) return false;
for (size_t i = 0; i < size; ++i) {
if (p[i] != 0) return false;
}
return true;
}
int main(void) {
mi_option_disable(mi_option_verbose);
CHECK_BODY("malloc-aligned9a") { void* p = mi_zalloc_aligned(1024 * 1024, 2);
mi_free(p);
p = mi_zalloc_aligned(1024 * 1024, 2);
mi_free(p);
result = true;
};
CHECK_BODY("malloc-zero") {
void* p = mi_malloc(0);
result = (p != NULL);
mi_free(p);
};
CHECK_BODY("malloc-nomem1") {
result = (mi_malloc((size_t)PTRDIFF_MAX + (size_t)1) == NULL);
};
CHECK_BODY("malloc-free-null") {
mi_free(NULL);
};
#if MI_INTPTR_BITS > 32
CHECK_BODY("malloc-free-invalid-low") {
mi_free((void*)(MI_ZU(0x0000000003990080))); };
#endif
CHECK_BODY("calloc-overflow") {
result = (mi_calloc((size_t)&mi_calloc,SIZE_MAX/1000) == NULL);
};
CHECK_BODY("calloc0") {
void* p = mi_calloc(0,1000);
result = (mi_usable_size(p) <= 16);
mi_free(p);
};
CHECK_BODY("malloc-large") { void* p = mi_malloc(67108872);
mi_free(p);
};
CHECK_BODY("posix_memalign1") {
void* p = &p;
int err = mi_posix_memalign(&p, sizeof(void*), 32);
result = ((err==0 && (uintptr_t)p % sizeof(void*) == 0) || p==&p);
mi_free(p);
};
CHECK_BODY("posix_memalign_no_align") {
void* p = &p;
int err = mi_posix_memalign(&p, 3, 32);
result = (err==EINVAL && p==&p);
};
CHECK_BODY("posix_memalign_zero") {
void* p = &p;
int err = mi_posix_memalign(&p, sizeof(void*), 0);
mi_free(p);
result = (err==0);
};
CHECK_BODY("posix_memalign_nopow2") {
void* p = &p;
int err = mi_posix_memalign(&p, 3*sizeof(void*), 32);
result = (err==EINVAL && p==&p);
};
CHECK_BODY("posix_memalign_nomem") {
void* p = &p;
int err = mi_posix_memalign(&p, sizeof(void*), SIZE_MAX);
result = (err==ENOMEM && p==&p);
};
CHECK_BODY("malloc-aligned1") {
void* p = mi_malloc_aligned(32,32); result = (p != NULL && (uintptr_t)(p) % 32 == 0); mi_free(p);
};
CHECK_BODY("malloc-aligned2") {
void* p = mi_malloc_aligned(48,32); result = (p != NULL && (uintptr_t)(p) % 32 == 0); mi_free(p);
};
CHECK_BODY("malloc-aligned3") {
void* p1 = mi_malloc_aligned(48,32); bool result1 = (p1 != NULL && (uintptr_t)(p1) % 32 == 0);
void* p2 = mi_malloc_aligned(48,32); bool result2 = (p2 != NULL && (uintptr_t)(p2) % 32 == 0);
mi_free(p2);
mi_free(p1);
result = (result1&&result2);
};
CHECK_BODY("malloc-aligned4") {
void* p;
bool ok = true;
for (int i = 0; i < 8 && ok; i++) {
p = mi_malloc_aligned(8, 16);
ok = (p != NULL && (uintptr_t)(p) % 16 == 0); mi_free(p);
}
result = ok;
};
CHECK_BODY("malloc-aligned5") {
void* p = mi_malloc_aligned(4097,4096);
size_t usable = mi_usable_size(p);
result = (usable >= 4097 && usable < 16000);
fprintf(stderr, "malloc_aligned5: usable size: %zi. ", usable);
mi_free(p);
};
CHECK_BODY("malloc-aligned7") {
void* p = mi_malloc_aligned(1024,MI_PAGE_MAX_OVERALLOC_ALIGN);
mi_free(p);
result = ((uintptr_t)p % MI_PAGE_MAX_OVERALLOC_ALIGN) == 0;
};
CHECK_BODY("malloc-aligned8") {
bool ok = true;
for (int i = 0; i < 5 && ok; i++) {
int n = (1 << i);
void* p = mi_malloc_aligned(1024, n * MI_PAGE_MAX_OVERALLOC_ALIGN);
ok = ((uintptr_t)p % (n*MI_PAGE_MAX_OVERALLOC_ALIGN)) == 0;
mi_free(p);
}
result = ok;
};
CHECK_BODY("malloc-aligned9") { bool ok = true;
void* p[8];
const int max_align_shift =
#if SIZE_MAX > UINT32_MAX
28
#else
20
#endif
;
size_t sizes[8] = { 8, 512, 1024 * 1024, MI_PAGE_MAX_OVERALLOC_ALIGN, MI_PAGE_MAX_OVERALLOC_ALIGN + 1, 2 * MI_PAGE_MAX_OVERALLOC_ALIGN, 8 * MI_PAGE_MAX_OVERALLOC_ALIGN, 0 };
for (int i = 0; i < max_align_shift && ok; i++) {
int align = (1 << i);
for (int j = 0; j < 8 && ok; j++) {
p[j] = mi_zalloc_aligned(sizes[j], align);
ok = ((uintptr_t)p[j] % align) == 0;
}
for (int j = 0; j < 8; j++) {
mi_free(p[j]);
}
}
result = ok;
};
CHECK_BODY("malloc-aligned10") {
bool ok = true;
void* p[10+1];
int align;
int j;
for(j = 0, align = 1; j <= 10 && ok; align *= 2, j++ ) {
p[j] = mi_malloc_aligned(43 + align, align);
ok = ((uintptr_t)p[j] % align) == 0;
}
for ( ; j > 0; j--) {
mi_free(p[j-1]);
}
result = ok;
}
CHECK_BODY("mimalloc-aligned12") {
void* p = mi_malloc_aligned(0x100, 0x100);
result = (((uintptr_t)p % 0x100) == 0); mi_free(p);
}
CHECK_BODY("mimalloc-aligned13") {
bool ok = true;
for( size_t size = 1; size <= (MI_SMALL_SIZE_MAX * 2) && ok; size++ ) {
for(size_t align = 1; align <= size && ok; align *= 2 ) {
void* p[10];
for(int i = 0; i < 10 && ok; i++) {
p[i] = mi_malloc_aligned(size,align);;
ok = (p[i] != NULL && ((uintptr_t)(p[i]) % align) == 0);
}
for(int i = 0; i < 10 && ok; i++) {
mi_free(p[i]);
}
}
}
result = ok;
}
CHECK_BODY("malloc-aligned-at1") {
void* p = mi_malloc_aligned_at(48,32,0); result = (p != NULL && ((uintptr_t)(p) + 0) % 32 == 0); mi_free(p);
};
CHECK_BODY("malloc-aligned-at2") {
void* p = mi_malloc_aligned_at(50,32,8); result = (p != NULL && ((uintptr_t)(p) + 8) % 32 == 0); mi_free(p);
};
CHECK_BODY("memalign1") {
void* p;
bool ok = true;
for (int i = 0; i < 8 && ok; i++) {
p = mi_memalign(16,8);
ok = (p != NULL && (uintptr_t)(p) % 16 == 0); mi_free(p);
}
result = ok;
};
CHECK_BODY("zalloc-aligned-small1") {
size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
result = mem_is_zero(p, zalloc_size);
mi_free(p);
};
CHECK_BODY("rezalloc_aligned-small1") {
size_t zalloc_size = MI_SMALL_SIZE_MAX / 2;
uint8_t* p = (uint8_t*)mi_zalloc_aligned(zalloc_size, MI_MAX_ALIGN_SIZE * 2);
result = mem_is_zero(p, zalloc_size);
zalloc_size *= 3;
p = (uint8_t*)mi_rezalloc_aligned(p, zalloc_size, MI_MAX_ALIGN_SIZE * 2);
result = result && mem_is_zero(p, zalloc_size);
mi_free(p);
};
CHECK_BODY("realloc-null") {
void* p = mi_realloc(NULL,4);
result = (p != NULL);
mi_free(p);
};
CHECK_BODY("realloc-null-sizezero") {
void* p = mi_realloc(NULL,0); result = (p != NULL);
mi_free(p);
};
CHECK_BODY("realloc-sizezero") {
void* p = mi_malloc(4);
void* q = mi_realloc(p, 0);
result = (q != NULL);
mi_free(q);
};
CHECK_BODY("reallocarray-null-sizezero") {
void* p = mi_reallocarray(NULL,0,16); result = (p != NULL && errno == 0);
mi_free(p);
};
CHECK_BODY("umalloc1") {
for(size_t size = 1; size <= 32*MI_MiB; size *= 2 ) {
size_t bsize;
void* p = mi_umalloc(size,&bsize);
assert(bsize >= size);
size_t pre_size;
size_t post_size;
p = mi_urealloc(p, size + 1024, &pre_size, &post_size);
assert(pre_size == bsize);
assert(post_size >= size + 1024);
size_t fsize;
mi_ufree(p,&fsize);
assert(fsize == post_size);
}
}
#if !defined(MI_TRACK_ASAN)
CHECK_BODY("realpath") {
char* s = mi_realpath( ".", NULL );
mi_free(s);
};
#endif
CHECK("stl_allocator1", test_stl_allocator1());
CHECK("stl_allocator2", test_stl_allocator2());
return print_test_summary();
}
bool test_stl_allocator1(void) {
#ifdef __cplusplus
std::vector<int, mi_stl_allocator<int> > vec;
vec.push_back(1);
vec.pop_back();
return vec.size() == 0;
#else
return true;
#endif
}
struct some_struct { int i; int j; double z; };
bool test_stl_allocator2(void) {
#ifdef __cplusplus
std::vector<some_struct, mi_stl_allocator<some_struct> > vec;
vec.push_back(some_struct());
vec.pop_back();
return vec.size() == 0;
#else
return true;
#endif
}