#include <malloc.h> | |
#include <common.h> | |
#include <config.h> | |
#define MARK (0xCD) | |
#define INICONTENT (0x0) | |
#define MARK_SIZE (4) | |
#define ALIGN_SIZE (sizeof(Align)) | |
#define REVALUEUPALIGN(val) ((val) ? (((val) - 1) / ALIGN_SIZE + 1) : 0) | |
#define HEADER_ALIGN_SIZE (REVALUEUPALIGN(sizeof(HeaderStruct))) | |
typedef union Header_tag Header; | |
static Header *g_Header = NULL; | |
typedef union | |
{ | |
long l_dummy; | |
double d_dummy; | |
void *p_dummy; | |
} Align; | |
typedef struct | |
{ | |
int size; | |
char *filename; | |
int line; | |
Header *prev; | |
Header *next; | |
unsigned char mark[MARK_SIZE]; | |
} HeaderStruct; | |
union Header_tag | |
{ | |
HeaderStruct s; | |
Align u[HEADER_ALIGN_SIZE]; | |
}; | |
static void chain_block(Header *header) | |
{ | |
if (g_Header) | |
{ | |
g_Header->s.prev = header; | |
} | |
header->s.prev = NULL; | |
header->s.next = g_Header; | |
g_Header = header; | |
} | |
static void unchain_block(Header *header) | |
{ | |
if (header->s.prev) | |
{ | |
header->s.prev->s.next = header->s.next; | |
} | |
else | |
{ | |
g_Header = header->s.next; | |
} | |
if (header->s.next) | |
{ | |
header->s.next->s.prev = header->s.prev; | |
} | |
} | |
static void set_header(Header *header, int size, char *filename, int line) | |
{ | |
header->s.size = size; | |
header->s.filename = filename; | |
header->s.line = line; | |
header->s.prev = NULL; | |
header->s.next = NULL; | |
memset(header->s.mark, MARK, (char*)&header[1] - (char*)header->s.mark); | |
} | |
static void set_tail(void *ptr, int alloc_size) | |
{ | |
char *tail; | |
tail = ((char*)ptr) + alloc_size - MARK_SIZE; | |
memset(tail, MARK, MARK_SIZE); | |
} | |
static int check_mark_sub(unsigned char *mark, int size) | |
{ | |
int i; | |
for (i = 0; i < size; i++) | |
{ | |
if (mark[i] != MARK) { | |
return -1; | |
} | |
} | |
return 0; | |
} | |
static int check_mark(Header *header) | |
{ | |
unsigned char *tail; | |
if (check_mark_sub(header->s.mark, (char*)&header[1] - (char*)header->s.mark)) | |
{ | |
printf("bad mark at header allocated in %s:%d\n", header->s.filename, header->s.line); | |
return -1; | |
} | |
tail = ((unsigned char*)header) + header->s.size + sizeof(Header); | |
if (check_mark_sub(tail, MARK_SIZE)) | |
{ | |
printf("bad mark at tail allocated in %s:%d\n", header->s.filename, header->s.line); | |
return -2; | |
} | |
return 0; | |
} | |
void* MEM_malloc(char *filename, int line, size_t size) | |
{ | |
void *ptr; | |
size_t alloc_size; | |
#if DEBUG | |
alloc_size = size + sizeof(Header) + MARK_SIZE; | |
#else | |
alloc_size = size; | |
#endif /* DEBUG */ | |
ptr = malloc(alloc_size); | |
if (ptr == NULL) | |
{ | |
return NULL; | |
} | |
#if DEBUG | |
memset(ptr, INICONTENT, alloc_size); | |
set_header(ptr, size, filename, line); | |
set_tail(ptr, alloc_size); | |
chain_block((Header*)ptr); | |
ptr = (char*)ptr + sizeof(Header); | |
#endif /* DEBUG */ | |
return ptr; | |
} | |
void MEM_free(void *ptr) | |
{ | |
void *real_ptr; | |
if (ptr == NULL) | |
return; | |
#if DEBUG | |
real_ptr = (char*)ptr - sizeof(Header); | |
check_mark((Header*)real_ptr); | |
unchain_block(real_ptr); | |
#else | |
real_ptr = ptr; | |
#endif /* DEBUG */ | |
free(real_ptr); | |
} | |