mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-06 15:29:31 +03:00
fix write to empty heap in mi_guarded build
This commit is contained in:
parent
68bd8744b7
commit
d9a2f76ff7
3 changed files with 56 additions and 23 deletions
|
@ -39,9 +39,10 @@ static mi_decl_restrict void* mi_heap_malloc_guarded_aligned(mi_heap_t* heap, si
|
||||||
|
|
||||||
static void* mi_heap_malloc_zero_no_guarded(mi_heap_t* heap, size_t size, bool zero) {
|
static void* mi_heap_malloc_zero_no_guarded(mi_heap_t* heap, size_t size, bool zero) {
|
||||||
const size_t rate = heap->guarded_sample_rate;
|
const size_t rate = heap->guarded_sample_rate;
|
||||||
heap->guarded_sample_rate = 0;
|
// only write if `rate!=0` so we don't write to the constant `_mi_heap_empty`
|
||||||
|
if (rate != 0) { heap->guarded_sample_rate = 0; }
|
||||||
void* p = _mi_heap_malloc_zero(heap, size, zero);
|
void* p = _mi_heap_malloc_zero(heap, size, zero);
|
||||||
heap->guarded_sample_rate = rate;
|
if (rate != 0) { heap->guarded_sample_rate = rate; }
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <mimalloc.h>
|
#include <mimalloc.h>
|
||||||
#include <mimalloc-override.h> // redefines malloc etc.
|
#include <mimalloc-override.h> // redefines malloc etc.
|
||||||
|
|
||||||
|
static void mi_bins(void);
|
||||||
|
|
||||||
static void double_free1();
|
static void double_free1();
|
||||||
static void double_free2();
|
static void double_free2();
|
||||||
static void corrupt_free();
|
static void corrupt_free();
|
||||||
|
@ -41,6 +43,9 @@ int main() {
|
||||||
// test_heap_walk();
|
// test_heap_walk();
|
||||||
// alloc_huge();
|
// alloc_huge();
|
||||||
|
|
||||||
|
// mi_bins();
|
||||||
|
|
||||||
|
|
||||||
void* p1 = malloc(78);
|
void* p1 = malloc(78);
|
||||||
void* p2 = malloc(24);
|
void* p2 = malloc(24);
|
||||||
free(p1);
|
free(p1);
|
||||||
|
@ -290,11 +295,11 @@ static void test_large_pages(void) {
|
||||||
static inline uint8_t mi_bsr32(uint32_t x);
|
static inline uint8_t mi_bsr32(uint32_t x);
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#include <windows.h>
|
//#include <Windows.h>
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
static inline uint8_t mi_bsr32(uint32_t x) {
|
static inline uint8_t mi_bsr32(uint32_t x) {
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
_BitScanReverse((DWORD*)&idx, x);
|
_BitScanReverse(&idx, x);
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
|
@ -318,7 +323,7 @@ static inline uint8_t mi_bsr32(uint32_t x) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
// Bit scan reverse: return the index of the highest bit.
|
// Bit scan reverse: return the index of the highest bit.
|
||||||
uint8_t _mi_bsr(uintptr_t x) {
|
uint8_t _mi_bsr(uintptr_t x) {
|
||||||
if (x == 0) return 0;
|
if (x == 0) return 0;
|
||||||
|
@ -331,7 +336,7 @@ uint8_t _mi_bsr(uintptr_t x) {
|
||||||
# error "define bsr for non-32 or 64-bit platforms"
|
# error "define bsr for non-32 or 64-bit platforms"
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
static inline size_t _mi_wsize_from_size(size_t size) {
|
static inline size_t _mi_wsize_from_size(size_t size) {
|
||||||
|
@ -408,11 +413,20 @@ static inline uint8_t _mi_bin4(size_t size) {
|
||||||
return bin;
|
return bin;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t _mi_binx4(size_t bsize) {
|
static size_t _mi_binx4(size_t wsize) {
|
||||||
if (bsize==0) return 0;
|
size_t bin;
|
||||||
uint8_t b = mi_bsr32((uint32_t)bsize);
|
if (wsize <= 1) {
|
||||||
if (b <= 1) return bsize;
|
bin = 1;
|
||||||
size_t bin = ((b << 1) | (bsize >> (b - 1))&0x01);
|
}
|
||||||
|
else if (wsize <= 8) {
|
||||||
|
// bin = (wsize+1)&~1; // round to double word sizes
|
||||||
|
bin = (uint8_t)wsize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint8_t b = mi_bsr32((uint32_t)wsize);
|
||||||
|
if (b <= 1) return wsize;
|
||||||
|
bin = ((b << 1) | (wsize >> (b - 1))&0x01) + 3;
|
||||||
|
}
|
||||||
return bin;
|
return bin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,22 +438,40 @@ static size_t _mi_binx8(size_t bsize) {
|
||||||
return bin;
|
return bin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline size_t mi_bin(size_t wsize) {
|
||||||
|
uint8_t bin;
|
||||||
|
if (wsize <= 1) {
|
||||||
|
bin = 1;
|
||||||
|
}
|
||||||
|
else if (wsize <= 8) {
|
||||||
|
// bin = (wsize+1)&~1; // round to double word sizes
|
||||||
|
bin = (uint8_t)wsize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wsize--;
|
||||||
|
// find the highest bit
|
||||||
|
uint8_t b = (uint8_t)mi_bsr32((uint32_t)wsize); // note: wsize != 0
|
||||||
|
// and use the top 3 bits to determine the bin (~12.5% worst internal fragmentation).
|
||||||
|
// - adjust with 3 because we use do not round the first 8 sizes
|
||||||
|
// which each get an exact bin
|
||||||
|
bin = ((b << 2) + (uint8_t)((wsize >> (b - 2)) & 0x03)) - 3;
|
||||||
|
}
|
||||||
|
return bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void mi_bins(void) {
|
static void mi_bins(void) {
|
||||||
//printf(" QNULL(1), /* 0 */ \\\n ");
|
//printf(" QNULL(1), /* 0 */ \\\n ");
|
||||||
size_t last_bin = 0;
|
size_t last_bin = 0;
|
||||||
size_t min_bsize = 0;
|
for (size_t wsize = 1; wsize <= (4*1024*1024) / 8 + 1024; wsize++) {
|
||||||
size_t last_bsize = 0;
|
size_t bin = mi_bin(wsize);
|
||||||
for (size_t bsize = 1; bsize < 2*1024; bsize++) {
|
|
||||||
size_t size = bsize * 64 * 1024;
|
|
||||||
size_t bin = _mi_binx8(bsize);
|
|
||||||
if (bin != last_bin) {
|
if (bin != last_bin) {
|
||||||
printf("min bsize: %6zd, max bsize: %6zd, bin: %6zd\n", min_bsize, last_bsize, last_bin);
|
//printf("min bsize: %6zd, max bsize: %6zd, bin: %6zd\n", min_wsize, last_wsize, last_bin);
|
||||||
//printf("QNULL(%6zd), ", wsize);
|
printf("QNULL(%6zd), ", wsize-1);
|
||||||
//if (last_bin%8 == 0) printf("/* %i */ \\\n ", last_bin);
|
if (last_bin%8 == 0) printf("/* %zu */ \\\n ", last_bin);
|
||||||
last_bin = bin;
|
last_bin = bin;
|
||||||
min_bsize = bsize;
|
|
||||||
}
|
}
|
||||||
last_bsize = bsize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,7 +42,7 @@ static int SCALE = 10;
|
||||||
static int ITER = 10;
|
static int ITER = 10;
|
||||||
#else
|
#else
|
||||||
static int THREADS = 32; // more repeatable if THREADS <= #processors
|
static int THREADS = 32; // more repeatable if THREADS <= #processors
|
||||||
static int SCALE = 25; // scaling factor
|
static int SCALE = 50; // scaling factor
|
||||||
static int ITER = 50; // N full iterations destructing and re-creating all threads
|
static int ITER = 50; // N full iterations destructing and re-creating all threads
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ static int ITER = 50; // N full iterations destructing and re-creating a
|
||||||
|
|
||||||
#define STRESS // undefine for leak test
|
#define STRESS // undefine for leak test
|
||||||
|
|
||||||
static bool allow_large_objects = true; // allow very large objects? (set to `true` if SCALE>100)
|
static bool allow_large_objects = false; // allow very large objects? (set to `true` if SCALE>100)
|
||||||
static size_t use_one_size = 0; // use single object size of `N * sizeof(uintptr_t)`?
|
static size_t use_one_size = 0; // use single object size of `N * sizeof(uintptr_t)`?
|
||||||
|
|
||||||
static bool main_participates = false; // main thread participates as a worker too
|
static bool main_participates = false; // main thread participates as a worker too
|
||||||
|
|
Loading…
Add table
Reference in a new issue