| #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); | |
| } | |