#if _WIN32
#include <windows.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <mimalloc.h>
#include <mimalloc-override.h>
static void mi_bins(void);
static void double_free1();
static void double_free2();
static void corrupt_free();
static void block_overflow1();
static void block_overflow2();
static void invalid_free();
static void test_aslr(void);
static void test_process_info(void);
static void test_reserved(void);
static void negative_stat(void);
static void alloc_huge(void);
static void test_heap_walk(void);
static void test_canary_leak(void);
static void test_manage_os_memory(void);
#if _WIN32
#include "main-static-dep.h"
static void test_dep(); #else
static void test_dep() {};
#endif
int main() {
mi_version();
mi_stats_reset();
test_dep();
test_canary_leak();
void* p1 = malloc(78);
void* p2 = malloc(24);
free(p1);
p1 = mi_malloc(8);
char* s = strdup("hello\n");
free(p2);
p2 = malloc(16);
p1 = realloc(p1, 32);
free(p1);
free(p2);
free(s);
return 0;
}
static void invalid_free() {
free((void*)0xBADBEEF);
realloc((void*)0xBADBEEF, 10);
}
static void block_overflow1() {
uint8_t* p = (uint8_t*)mi_malloc(17);
p[18] = 0;
free(p);
}
static void block_overflow2() {
uint8_t* p = (uint8_t*)mi_malloc(16);
p[17] = 0;
free(p);
}
static void double_free1() {
void* p[256];
p[0] = mi_malloc(622616);
p[1] = mi_malloc(655362);
p[2] = mi_malloc(786432);
mi_free(p[2]);
mi_free(p[2]);
p[3] = mi_malloc(786456);
fprintf(stderr, "p3: %p-%p, p1: %p-%p, p2: %p\n", p[3], (uint8_t*)(p[3]) + 786456, p[1], (uint8_t*)(p[1]) + 655362, p[2]);
}
static void double_free2() {
void* p[256];
p[0] = malloc(712352);
p[1] = malloc(786432);
free(p[0]);
free(p[0]);
p[2] = malloc(786440);
p[3] = malloc(917504);
p[4] = malloc(786440);
fprintf(stderr, "p1: %p-%p, p2: %p-%p\n", p[4], (uint8_t*)(p[4]) + 917504, p[1], (uint8_t*)(p[1]) + 786432);
}
#define N 256
#define SZ 64
static void corrupt_free() {
void* p[N];
for (int i = 0; i < N; i++) {
p[i] = malloc(SZ);
}
for (int i = 0; i < N; i += (N/10)) {
free(p[i]);
p[i] = NULL;
}
for (int i = 0; i < N; i++) {
if (p[i] != NULL) {
memset(p[i], 0, SZ+8);
}
}
for (int i = 0; i < 4096; i++) {
malloc(SZ);
}
}
static void test_aslr(void) {
void* p[256];
p[0] = malloc(378200);
p[1] = malloc(1134626);
printf("p1: %p, p2: %p\n", p[0], p[1]);
}
static void test_process_info(void) {
size_t elapsed = 0;
size_t user_msecs = 0;
size_t system_msecs = 0;
size_t current_rss = 0;
size_t peak_rss = 0;
size_t current_commit = 0;
size_t peak_commit = 0;
size_t page_faults = 0;
for (int i = 0; i < 100000; i++) {
void* p = calloc(100, 10);
free(p);
}
mi_process_info(&elapsed, &user_msecs, &system_msecs, ¤t_rss, &peak_rss, ¤t_commit, &peak_commit, &page_faults);
printf("\n\n*** process info: elapsed %3zd.%03zd s, user: %3zd.%03zd s, rss: %zd b, commit: %zd b\n\n", elapsed/1000, elapsed%1000, user_msecs/1000, user_msecs%1000, peak_rss, peak_commit);
}
static void test_reserved(void) {
#define KiB 1024UL
#define MiB (KiB*KiB)
#define GiB (MiB*KiB)
mi_reserve_os_memory(3500*MiB, false, true);
void* p1 = malloc(100);
void* p2 = malloc(100000);
void* p3 = malloc(2*GiB);
void* p4 = malloc(1*GiB + 100000);
free(p1);
free(p2);
free(p3);
p3 = malloc(1*GiB);
free(p4);
}
static void negative_stat(void) {
int* p = mi_malloc(60000);
mi_stats_print_out(NULL, NULL);
*p = 100;
mi_free(p);
mi_stats_print_out(NULL, NULL);
}
static void alloc_huge(void) {
void* p = mi_malloc(67108872);
mi_free(p);
}
static bool test_visit(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg) {
if (block == NULL) {
printf("visiting an area with blocks of size %zu (including padding)\n", area->full_block_size);
}
else {
printf(" block of size %zu (allocated size is %zu)\n", block_size, mi_usable_size(block));
}
return true;
}
static void test_heap_walk(void) {
mi_heap_t* heap = mi_heap_new();
mi_heap_malloc(heap, 16*2097152);
mi_heap_malloc(heap, 2067152);
mi_heap_malloc(heap, 2097160);
mi_heap_malloc(heap, 24576);
mi_heap_visit_blocks(heap, true, &test_visit, NULL);
}
static void test_canary_leak(void) {
char* p = mi_mallocn_tp(char, 22);
for (int i = 0; i < 22; i++) {
p[i] = '0'+i;
}
puts(p);
free(p);
}
#if _WIN32
static void test_manage_os_memory(void) {
size_t size = 256 * 1024 * 1024;
void* ptr = VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
mi_arena_id_t arena_id;
mi_manage_os_memory_ex(ptr, size, true , true , false , -1 , true , &arena_id);
mi_heap_t* cuda_theap = mi_heap_new_in_arena(arena_id);
void* p1 = mi_heap_malloc(cuda_theap, 8);
int* p2 = mi_heap_malloc_tp(int,cuda_theap);
*p2 = 42;
{
mi_theap_t* prev_default_theap = mi_theap_set_default(mi_heap_theap(cuda_theap));
void* p3 = mi_malloc(8); mi_free(p3);
}
mi_free(p1);
mi_free(p2);
}
#else
static void test_manage_os_memory(void) {
}
#endif
#if _WIN32
static void call_library(void) {
HMODULE dll = LoadLibraryA("mimalloc-test-static-dep.dll");
if (dll != NULL) {
TestFun fun = (TestFun)GetProcAddress(dll, "Test");
if (fun != NULL) {
fun();
}
bool ok = FreeLibrary(dll);
}
}
static void test_dep(void) {
call_library();
call_library();
}
#endif
#if 0#endif
#if 0#endif