Align memory with MALLOC_DEBUG (nw)

This commit is contained in:
Vas Crabb 2015-07-04 00:37:56 +10:00
parent 454895659e
commit eb38a7ad25

View File

@ -36,6 +36,16 @@
// align allocations to start or end of the page? // align allocations to start or end of the page?
#define GUARD_ALIGN_START 0 #define GUARD_ALIGN_START 0
#if defined(__BIGGEST_ALIGNMENT__)
#define MAX_ALIGNMENT __BIGGEST_ALIGNMENT__
#elif defined(__AVX__)
#define MAX_ALIGNMENT 32
#elif defined(__SSE__) || defined(__x86_64__) || defined(_M_X64)
#define MAX_ALIGNMENT 16
#else
#define MAX_ALIGNMENT sizeof(INT64)
#endif
//============================================================ //============================================================
// GLOBAL VARIABLES // GLOBAL VARIABLES
@ -114,15 +124,20 @@ void *osd_malloc(size_t size)
#ifndef MALLOC_DEBUG #ifndef MALLOC_DEBUG
return malloc(size); return malloc(size);
#else #else
// add in space for the size // add in space for the size and offset
size += sizeof(size_t); size += MAX_ALIGNMENT + sizeof(size_t) + 2;
size &= ~size_t(1);
// basic objects just come from the heap // basic objects just come from the heap
void *result = HeapAlloc(GetProcessHeap(), 0, size); UINT8 *const block = reinterpret_cast<UINT8 *>(HeapAlloc(GetProcessHeap(), 0, size));
if (block == NULL)
return NULL;
UINT8 *const result = reinterpret_cast<UINT8 *>(reinterpret_cast<FPTR>(block + sizeof(size_t) + MAX_ALIGNMENT) & ~(FPTR(MAX_ALIGNMENT) - 1));
// store the size and return and pointer to the data afterward // store the size and return and pointer to the data afterward
*reinterpret_cast<size_t *>(result) = size; *reinterpret_cast<size_t *>(block) = size;
return reinterpret_cast<UINT8 *>(result) + sizeof(size_t); *(result - 1) = result - block;
return result;
#endif #endif
} }
@ -136,11 +151,12 @@ void *osd_malloc_array(size_t size)
#ifndef MALLOC_DEBUG #ifndef MALLOC_DEBUG
return malloc(size); return malloc(size);
#else #else
// add in space for the size // add in space for the size and offset
size += sizeof(size_t); size += MAX_ALIGNMENT + sizeof(size_t) + 2;
size &= ~size_t(1);
// round the size up to a page boundary // round the size up to a page boundary
size_t rounded_size = ((size + sizeof(void *) + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; size_t const rounded_size = ((size + sizeof(void *) + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
// reserve that much memory, plus two guard pages // reserve that much memory, plus two guard pages
void *page_base = VirtualAlloc(NULL, rounded_size + 2 * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS); void *page_base = VirtualAlloc(NULL, rounded_size + 2 * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS);
@ -153,11 +169,13 @@ void *osd_malloc_array(size_t size)
return NULL; return NULL;
// work backwards from the page base to get to the block base // work backwards from the page base to get to the block base
void *result = GUARD_ALIGN_START ? page_base : (reinterpret_cast<UINT8 *>(page_base) + rounded_size - size); UINT8 *const block = GUARD_ALIGN_START ? reinterpret_cast<UINT8 *>(page_base) : (reinterpret_cast<UINT8 *>(page_base) + rounded_size - size);
UINT8 *const result = reinterpret_cast<UINT8 *>(reinterpret_cast<FPTR>(block + sizeof(size_t) + MAX_ALIGNMENT) & ~(FPTR(MAX_ALIGNMENT) - 1));
// store the size at the start with a flag indicating it has a guard page // store the size at the start with a flag indicating it has a guard page
*reinterpret_cast<size_t *>(result) = size | 0x80000000; *reinterpret_cast<size_t *>(block) = size | 1;
return reinterpret_cast<UINT8 *>(result) + sizeof(size_t); *(result - 1) = result - block;
return result;
#endif #endif
} }
@ -171,16 +189,19 @@ void osd_free(void *ptr)
#ifndef MALLOC_DEBUG #ifndef MALLOC_DEBUG
free(ptr); free(ptr);
#else #else
size_t size = reinterpret_cast<size_t *>(ptr)[-1]; UINT8 const offset = *(reinterpret_cast<UINT8 *>(ptr) - 1);
UINT8 *const block = reinterpret_cast<UINT8 *>(ptr) - offset;
size_t const size = *reinterpret_cast<size_t *>(block);
// if no guard page, just free the pointer if ((size & 0x1) == 0)
if ((size & 0x80000000) == 0) {
HeapFree(GetProcessHeap(), 0, reinterpret_cast<UINT8 *>(ptr) - sizeof(size_t)); // if no guard page, just free the pointer
HeapFree(GetProcessHeap(), 0, block);
// large items need more care }
else else
{ {
ULONG_PTR page_base = (reinterpret_cast<ULONG_PTR>(ptr) - sizeof(size_t)) & ~(PAGE_SIZE - 1); // large items need more care
ULONG_PTR const page_base = reinterpret_cast<ULONG_PTR>(block) & ~(PAGE_SIZE - 1);
VirtualFree(reinterpret_cast<void *>(page_base - PAGE_SIZE), 0, MEM_RELEASE); VirtualFree(reinterpret_cast<void *>(page_base - PAGE_SIZE), 0, MEM_RELEASE);
} }
#endif #endif