diff options
author | brianluau <brianluau@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-12-05 02:53:33 +0000 |
---|---|---|
committer | brianluau <brianluau@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-12-05 02:53:33 +0000 |
commit | 60a426c0742b3e7d8c5b557c7578df6eeeea377b (patch) | |
tree | 5d01f9ccc2798309f9b13f07c0096ed97c6a85c8 /src/common/malloc.c | |
parent | 621db2441f69736a6c8f10d26bf966d5414fac74 (diff) | |
download | hercules-60a426c0742b3e7d8c5b557c7578df6eeeea377b.tar.gz hercules-60a426c0742b3e7d8c5b557c7578df6eeeea377b.tar.bz2 hercules-60a426c0742b3e7d8c5b557c7578df6eeeea377b.tar.xz hercules-60a426c0742b3e7d8c5b557c7578df6eeeea377b.zip |
- Undid r16968: SVN Replaced with source:/trunk/src/@16966 (tid:74924).
[16969:16991/trunk/src/] will be re-committed in the next 24 hours.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16992 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/common/malloc.c')
-rw-r--r-- | src/common/malloc.c | 1006 |
1 files changed, 508 insertions, 498 deletions
diff --git a/src/common/malloc.c b/src/common/malloc.c index 396ec33cb..9976a28d5 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -14,109 +14,109 @@ #if defined(MEMWATCH) -# include <string.h> -# include "memwatch.h" -# define MALLOC(n,file,line,func) mwMalloc((n),(file),(line)) -# define CALLOC(m,n,file,line,func) mwCalloc((m),(n),(file),(line)) -# define REALLOC(p,n,file,line,func) mwRealloc((p),(n),(file),(line)) -# define STRDUP(p,file,line,func) mwStrdup((p),(file),(line)) -# define FREE(p,file,line,func) mwFree((p),(file),(line)) -# define MEMORY_USAGE() 0 -# define MEMORY_VERIFY(ptr) mwIsSafeAddr(ptr, 1) -# define MEMORY_CHECK() CHECK() +# include <string.h> +# include "memwatch.h" +# define MALLOC(n,file,line,func) mwMalloc((n),(file),(line)) +# define CALLOC(m,n,file,line,func) mwCalloc((m),(n),(file),(line)) +# define REALLOC(p,n,file,line,func) mwRealloc((p),(n),(file),(line)) +# define STRDUP(p,file,line,func) mwStrdup((p),(file),(line)) +# define FREE(p,file,line,func) mwFree((p),(file),(line)) +# define MEMORY_USAGE() 0 +# define MEMORY_VERIFY(ptr) mwIsSafeAddr(ptr, 1) +# define MEMORY_CHECK() CHECK() #elif defined(DMALLOC) -# include <string.h> -# include <stdlib.h> -# include "dmalloc.h" -# define MALLOC(n,file,line,func) dmalloc_malloc((file),(line),(n),DMALLOC_FUNC_MALLOC,0,0) -# define CALLOC(m,n,file,line,func) dmalloc_malloc((file),(line),(m)*(n),DMALLOC_FUNC_CALLOC,0,0) -# define REALLOC(p,n,file,line,func) dmalloc_realloc((file),(line),(p),(n),DMALLOC_FUNC_REALLOC,0) -# define STRDUP(p,file,line,func) strdup(p) -# define FREE(p,file,line,func) free(p) -# define MEMORY_USAGE() dmalloc_memory_allocated() -# define MEMORY_VERIFY(ptr) (dmalloc_verify(ptr) == DMALLOC_VERIFY_NOERROR) -# define MEMORY_CHECK() dmalloc_log_stats(); dmalloc_log_unfreed() +# include <string.h> +# include <stdlib.h> +# include "dmalloc.h" +# define MALLOC(n,file,line,func) dmalloc_malloc((file),(line),(n),DMALLOC_FUNC_MALLOC,0,0) +# define CALLOC(m,n,file,line,func) dmalloc_malloc((file),(line),(m)*(n),DMALLOC_FUNC_CALLOC,0,0) +# define REALLOC(p,n,file,line,func) dmalloc_realloc((file),(line),(p),(n),DMALLOC_FUNC_REALLOC,0) +# define STRDUP(p,file,line,func) strdup(p) +# define FREE(p,file,line,func) free(p) +# define MEMORY_USAGE() dmalloc_memory_allocated() +# define MEMORY_VERIFY(ptr) (dmalloc_verify(ptr) == DMALLOC_VERIFY_NOERROR) +# define MEMORY_CHECK() dmalloc_log_stats(); dmalloc_log_unfreed() #elif defined(GCOLLECT) -# include "gc.h" -# ifdef GC_ADD_CALLER -# define RETURN_ADDR 0, -# else -# define RETURN_ADDR -# endif -# define MALLOC(n,file,line,func) GC_debug_malloc((n), RETURN_ADDR (file),(line)) -# define CALLOC(m,n,file,line,func) GC_debug_malloc((m)*(n), RETURN_ADDR (file),(line)) -# define REALLOC(p,n,file,line,func) GC_debug_realloc((p),(n), RETURN_ADDR (file),(line)) -# define STRDUP(p,file,line,func) GC_debug_strdup((p), RETURN_ADDR (file),(line)) -# define FREE(p,file,line,func) GC_debug_free(p) -# define MEMORY_USAGE() GC_get_heap_size() -# define MEMORY_VERIFY(ptr) (GC_base(ptr) != NULL) -# define MEMORY_CHECK() GC_gcollect() +# include "gc.h" +# ifdef GC_ADD_CALLER +# define RETURN_ADDR 0, +# else +# define RETURN_ADDR +# endif +# define MALLOC(n,file,line,func) GC_debug_malloc((n), RETURN_ADDR (file),(line)) +# define CALLOC(m,n,file,line,func) GC_debug_malloc((m)*(n), RETURN_ADDR (file),(line)) +# define REALLOC(p,n,file,line,func) GC_debug_realloc((p),(n), RETURN_ADDR (file),(line)) +# define STRDUP(p,file,line,func) GC_debug_strdup((p), RETURN_ADDR (file),(line)) +# define FREE(p,file,line,func) GC_debug_free(p) +# define MEMORY_USAGE() GC_get_heap_size() +# define MEMORY_VERIFY(ptr) (GC_base(ptr) != NULL) +# define MEMORY_CHECK() GC_gcollect() #else -# define MALLOC(n,file,line,func) malloc(n) -# define CALLOC(m,n,file,line,func) calloc((m),(n)) -# define REALLOC(p,n,file,line,func) realloc((p),(n)) -# define STRDUP(p,file,line,func) strdup(p) -# define FREE(p,file,line,func) free(p) -# define MEMORY_USAGE() 0 -# define MEMORY_VERIFY(ptr) true -# define MEMORY_CHECK() +# define MALLOC(n,file,line,func) malloc(n) +# define CALLOC(m,n,file,line,func) calloc((m),(n)) +# define REALLOC(p,n,file,line,func) realloc((p),(n)) +# define STRDUP(p,file,line,func) strdup(p) +# define FREE(p,file,line,func) free(p) +# define MEMORY_USAGE() 0 +# define MEMORY_VERIFY(ptr) true +# define MEMORY_CHECK() #endif -void *aMalloc_(size_t size, const char *file, int line, const char *func) +void* aMalloc_(size_t size, const char *file, int line, const char *func) { - void *ret = MALLOC(size, file, line, func); - // ShowMessage("%s:%d: in func %s: aMalloc %d\n",file,line,func,size); - if (ret == NULL) { - ShowFatalError("%s:%d: in func %s: aMalloc error out of memory!\n",file,line,func); - exit(EXIT_FAILURE); - } - - return ret; + void *ret = MALLOC(size, file, line, func); + // ShowMessage("%s:%d: in func %s: aMalloc %d\n",file,line,func,size); + if (ret == NULL){ + ShowFatalError("%s:%d: in func %s: aMalloc error out of memory!\n",file,line,func); + exit(EXIT_FAILURE); + } + + return ret; } -void *aCalloc_(size_t num, size_t size, const char *file, int line, const char *func) +void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func) { - void *ret = CALLOC(num, size, file, line, func); - // ShowMessage("%s:%d: in func %s: aCalloc %d %d\n",file,line,func,num,size); - if (ret == NULL) { - ShowFatalError("%s:%d: in func %s: aCalloc error out of memory!\n", file, line, func); - exit(EXIT_FAILURE); - } - return ret; + void *ret = CALLOC(num, size, file, line, func); + // ShowMessage("%s:%d: in func %s: aCalloc %d %d\n",file,line,func,num,size); + if (ret == NULL){ + ShowFatalError("%s:%d: in func %s: aCalloc error out of memory!\n", file, line, func); + exit(EXIT_FAILURE); + } + return ret; } -void *aRealloc_(void *p, size_t size, const char *file, int line, const char *func) +void* aRealloc_(void *p, size_t size, const char *file, int line, const char *func) { - void *ret = REALLOC(p, size, file, line, func); - // ShowMessage("%s:%d: in func %s: aRealloc %p %d\n",file,line,func,p,size); - if (ret == NULL) { - ShowFatalError("%s:%d: in func %s: aRealloc error out of memory!\n",file,line,func); - exit(EXIT_FAILURE); - } - return ret; + void *ret = REALLOC(p, size, file, line, func); + // ShowMessage("%s:%d: in func %s: aRealloc %p %d\n",file,line,func,p,size); + if (ret == NULL){ + ShowFatalError("%s:%d: in func %s: aRealloc error out of memory!\n",file,line,func); + exit(EXIT_FAILURE); + } + return ret; } -char *aStrdup_(const char *p, const char *file, int line, const char *func) +char* aStrdup_(const char *p, const char *file, int line, const char *func) { - char *ret = STRDUP(p, file, line, func); - // ShowMessage("%s:%d: in func %s: aStrdup %p\n",file,line,func,p); - if (ret == NULL) { - ShowFatalError("%s:%d: in func %s: aStrdup error out of memory!\n", file, line, func); - exit(EXIT_FAILURE); - } - return ret; + char *ret = STRDUP(p, file, line, func); + // ShowMessage("%s:%d: in func %s: aStrdup %p\n",file,line,func,p); + if (ret == NULL){ + ShowFatalError("%s:%d: in func %s: aStrdup error out of memory!\n", file, line, func); + exit(EXIT_FAILURE); + } + return ret; } void aFree_(void *p, const char *file, int line, const char *func) { - // ShowMessage("%s:%d: in func %s: aFree %p\n",file,line,func,p); - if (p) - FREE(p, file, line, func); + // ShowMessage("%s:%d: in func %s: aFree %p\n",file,line,func,p); + if (p) + FREE(p, file, line, func); - p = NULL; + p = NULL; } @@ -146,397 +146,405 @@ void aFree_(void *p, const char *file, int line, const char *func) */ /* ブロックのアライメント */ -#define BLOCK_ALIGNMENT1 16 -#define BLOCK_ALIGNMENT2 64 +#define BLOCK_ALIGNMENT1 16 +#define BLOCK_ALIGNMENT2 64 /* ブロックに入るデータ量 */ -#define BLOCK_DATA_COUNT1 128 -#define BLOCK_DATA_COUNT2 608 +#define BLOCK_DATA_COUNT1 128 +#define BLOCK_DATA_COUNT2 608 /* ブロックの大きさ: 16*128 + 64*576 = 40KB */ -#define BLOCK_DATA_SIZE1 ( BLOCK_ALIGNMENT1 * BLOCK_DATA_COUNT1 ) -#define BLOCK_DATA_SIZE2 ( BLOCK_ALIGNMENT2 * BLOCK_DATA_COUNT2 ) -#define BLOCK_DATA_SIZE ( BLOCK_DATA_SIZE1 + BLOCK_DATA_SIZE2 ) +#define BLOCK_DATA_SIZE1 ( BLOCK_ALIGNMENT1 * BLOCK_DATA_COUNT1 ) +#define BLOCK_DATA_SIZE2 ( BLOCK_ALIGNMENT2 * BLOCK_DATA_COUNT2 ) +#define BLOCK_DATA_SIZE ( BLOCK_DATA_SIZE1 + BLOCK_DATA_SIZE2 ) /* 一度に確保するブロックの数。 */ -#define BLOCK_ALLOC 104 +#define BLOCK_ALLOC 104 /* ブロック */ struct block { - struct block *block_next; /* 次に確保した領域 */ - struct block *unfill_prev; /* 次の埋まっていない領域 */ - struct block *unfill_next; /* 次の埋まっていない領域 */ - unsigned short unit_size; /* ユニットの大きさ */ - unsigned short unit_hash; /* ユニットのハッシュ */ - unsigned short unit_count; /* ユニットの個数 */ - unsigned short unit_used; /* 使用ユニット数 */ - unsigned short unit_unfill; /* 未使用ユニットの場所 */ - unsigned short unit_maxused; /* 使用ユニットの最大値 */ - char data[ BLOCK_DATA_SIZE ]; + struct block* block_next; /* 次に確保した領域 */ + struct block* unfill_prev; /* 次の埋まっていない領域 */ + struct block* unfill_next; /* 次の埋まっていない領域 */ + unsigned short unit_size; /* ユニットの大きさ */ + unsigned short unit_hash; /* ユニットのハッシュ */ + unsigned short unit_count; /* ユニットの個数 */ + unsigned short unit_used; /* 使用ユニット数 */ + unsigned short unit_unfill; /* 未使用ユニットの場所 */ + unsigned short unit_maxused; /* 使用ユニットの最大値 */ + char data[ BLOCK_DATA_SIZE ]; }; struct unit_head { - struct block *block; - const char *file; - unsigned short line; - unsigned short size; - long checksum; + struct block *block; + const char* file; + unsigned short line; + unsigned short size; + long checksum; }; -static struct block *hash_unfill[BLOCK_DATA_COUNT1 + BLOCK_DATA_COUNT2 + 1]; -static struct block *block_first, *block_last, block_head; +static struct block* hash_unfill[BLOCK_DATA_COUNT1 + BLOCK_DATA_COUNT2 + 1]; +static struct block* block_first, *block_last, block_head; /* メモリを使い回せない領域用のデータ */ struct unit_head_large { - size_t size; - struct unit_head_large *prev; - struct unit_head_large *next; - struct unit_head unit_head; + size_t size; + struct unit_head_large* prev; + struct unit_head_large* next; + struct unit_head unit_head; }; static struct unit_head_large *unit_head_large_first = NULL; -static struct block *block_malloc(unsigned short hash); -static void block_free(struct block *p); +static struct block* block_malloc(unsigned short hash); +static void block_free(struct block* p); static size_t memmgr_usage_bytes; #define block2unit(p, n) ((struct unit_head*)(&(p)->data[ p->unit_size * (n) ])) #define memmgr_assert(v) do { if(!(v)) { ShowError("Memory manager: assertion '" #v "' failed!\n"); } } while(0) -static unsigned short size2hash(size_t size) +static unsigned short size2hash( size_t size ) { - if (size <= BLOCK_DATA_SIZE1) { - return (unsigned short)(size + BLOCK_ALIGNMENT1 - 1) / BLOCK_ALIGNMENT1; - } else if (size <= BLOCK_DATA_SIZE) { - return (unsigned short)(size - BLOCK_DATA_SIZE1 + BLOCK_ALIGNMENT2 - 1) / BLOCK_ALIGNMENT2 - + BLOCK_DATA_COUNT1; - } else { - return 0xffff; // ブロック長を超える場合は hash にしない - } + if( size <= BLOCK_DATA_SIZE1 ) { + return (unsigned short)(size + BLOCK_ALIGNMENT1 - 1) / BLOCK_ALIGNMENT1; + } else if( size <= BLOCK_DATA_SIZE ){ + return (unsigned short)(size - BLOCK_DATA_SIZE1 + BLOCK_ALIGNMENT2 - 1) / BLOCK_ALIGNMENT2 + + BLOCK_DATA_COUNT1; + } else { + return 0xffff; // ブロック長を超える場合は hash にしない + } } -static size_t hash2size(unsigned short hash) +static size_t hash2size( unsigned short hash ) { - if (hash <= BLOCK_DATA_COUNT1) { - return hash * BLOCK_ALIGNMENT1; - } else { - return (hash - BLOCK_DATA_COUNT1) * BLOCK_ALIGNMENT2 + BLOCK_DATA_SIZE1; - } + if( hash <= BLOCK_DATA_COUNT1) { + return hash * BLOCK_ALIGNMENT1; + } else { + return (hash - BLOCK_DATA_COUNT1) * BLOCK_ALIGNMENT2 + BLOCK_DATA_SIZE1; + } } -void *_mmalloc(size_t size, const char *file, int line, const char *func) +void* _mmalloc(size_t size, const char *file, int line, const char *func ) { - struct block *block; - short size_hash = size2hash(size); - struct unit_head *head; - - if (((long) size) < 0) { - ShowError("_mmalloc: %d\n", size); - return NULL; - } - - if (size == 0) { - return NULL; - } - memmgr_usage_bytes += size; - - /* ブロック長を超える領域の確保には、malloc() を用いる */ - /* その際、unit_head.block に NULL を代入して区別する */ - if (hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { - struct unit_head_large *p = (struct unit_head_large *)MALLOC(sizeof(struct unit_head_large)+size,file,line,func); - if (p != NULL) { - p->size = size; - p->unit_head.block = NULL; - p->unit_head.size = 0; - p->unit_head.file = file; - p->unit_head.line = line; - p->prev = NULL; - if (unit_head_large_first == NULL) - p->next = NULL; - else { - unit_head_large_first->prev = p; - p->next = unit_head_large_first; - } - unit_head_large_first = p; - *(long *)((char *)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf; - return (char *)p + sizeof(struct unit_head_large) - sizeof(long); - } else { - ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line); - exit(EXIT_FAILURE); - } - } - - /* 同一サイズのブロックが確保されていない時、新たに確保する */ - if (hash_unfill[size_hash]) { - block = hash_unfill[size_hash]; - } else { - block = block_malloc(size_hash); - } - - if (block->unit_unfill == 0xFFFF) { - // free済み領域が残っていない - memmgr_assert(block->unit_used < block->unit_count); - memmgr_assert(block->unit_used == block->unit_maxused); - head = block2unit(block, block->unit_maxused); - block->unit_used++; - block->unit_maxused++; - } else { - head = block2unit(block, block->unit_unfill); - block->unit_unfill = head->size; - block->unit_used++; - } - - if (block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) { - // ユニットを使い果たしたので、unfillリストから削除 - if (block->unfill_prev == &block_head) { - hash_unfill[ size_hash ] = block->unfill_next; - } else { - block->unfill_prev->unfill_next = block->unfill_next; - } - if (block->unfill_next) { - block->unfill_next->unfill_prev = block->unfill_prev; - } - block->unfill_prev = NULL; - } + struct block *block; + short size_hash = size2hash( size ); + struct unit_head *head; + + if (((long) size) < 0) { + ShowError("_mmalloc: %d\n", size); + return NULL; + } + + if(size == 0) { + return NULL; + } + memmgr_usage_bytes += size; + + /* ブロック長を超える領域の確保には、malloc() を用いる */ + /* その際、unit_head.block に NULL を代入して区別する */ + if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { + struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func); + if(p != NULL) { + p->size = size; + p->unit_head.block = NULL; + p->unit_head.size = 0; + p->unit_head.file = file; + p->unit_head.line = line; + p->prev = NULL; + if (unit_head_large_first == NULL) + p->next = NULL; + else { + unit_head_large_first->prev = p; + p->next = unit_head_large_first; + } + unit_head_large_first = p; + *(long*)((char*)p + sizeof(struct unit_head_large) - sizeof(long) + size) = 0xdeadbeaf; + return (char *)p + sizeof(struct unit_head_large) - sizeof(long); + } else { + ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line); + exit(EXIT_FAILURE); + } + } + + /* 同一サイズのブロックが確保されていない時、新たに確保する */ + if(hash_unfill[size_hash]) { + block = hash_unfill[size_hash]; + } else { + block = block_malloc(size_hash); + } + + if( block->unit_unfill == 0xFFFF ) { + // free済み領域が残っていない + memmgr_assert(block->unit_used < block->unit_count); + memmgr_assert(block->unit_used == block->unit_maxused); + head = block2unit(block, block->unit_maxused); + block->unit_used++; + block->unit_maxused++; + } else { + head = block2unit(block, block->unit_unfill); + block->unit_unfill = head->size; + block->unit_used++; + } + + if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) { + // ユニットを使い果たしたので、unfillリストから削除 + if( block->unfill_prev == &block_head) { + hash_unfill[ size_hash ] = block->unfill_next; + } else { + block->unfill_prev->unfill_next = block->unfill_next; + } + if( block->unfill_next ) { + block->unfill_next->unfill_prev = block->unfill_prev; + } + block->unfill_prev = NULL; + } #ifdef DEBUG_MEMMGR - { - size_t i, sz = hash2size(size_hash); - for (i=0; i<sz; i++) { - if (((unsigned char *)head)[ sizeof(struct unit_head) - sizeof(long) + i] != 0xfd) { - if (head->line != 0xfdfd) { - ShowError("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line); - } else { - ShowError("Memory manager: not-allocated-data is changed.\n"); - } - break; - } - } - memset((char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz); - } + { + size_t i, sz = hash2size( size_hash ); + for( i=0; i<sz; i++ ) + { + if( ((unsigned char*)head)[ sizeof(struct unit_head) - sizeof(long) + i] != 0xfd ) + { + if( head->line != 0xfdfd ) + { + ShowError("Memory manager: freed-data is changed. (freed in %s line %d)\n", head->file,head->line); + } + else + { + ShowError("Memory manager: not-allocated-data is changed.\n"); + } + break; + } + } + memset( (char *)head + sizeof(struct unit_head) - sizeof(long), 0xcd, sz ); + } #endif - head->block = block; - head->file = file; - head->line = line; - head->size = (unsigned short)size; - *(long *)((char *)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf; - return (char *)head + sizeof(struct unit_head) - sizeof(long); + head->block = block; + head->file = file; + head->line = line; + head->size = (unsigned short)size; + *(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf; + return (char *)head + sizeof(struct unit_head) - sizeof(long); } -void *_mcalloc(size_t num, size_t size, const char *file, int line, const char *func) +void* _mcalloc(size_t num, size_t size, const char *file, int line, const char *func ) { - void *p = _mmalloc(num * size,file,line,func); - memset(p,0,num * size); - return p; + void *p = _mmalloc(num * size,file,line,func); + memset(p,0,num * size); + return p; } -void *_mrealloc(void *memblock, size_t size, const char *file, int line, const char *func) +void* _mrealloc(void *memblock, size_t size, const char *file, int line, const char *func ) { - size_t old_size; - if (memblock == NULL) { - return _mmalloc(size,file,line,func); - } - - old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size; - if (old_size == 0) { - old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size; - } - if (old_size > size) { - // サイズ縮小 -> そのまま返す(手抜き) - return memblock; - } else { - // サイズ拡大 - void *p = _mmalloc(size,file,line,func); - if (p != NULL) { - memcpy(p,memblock,old_size); - } - _mfree(memblock,file,line,func); - return p; - } + size_t old_size; + if(memblock == NULL) { + return _mmalloc(size,file,line,func); + } + + old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size; + if( old_size == 0 ) { + old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size; + } + if(old_size > size) { + // サイズ縮小 -> そのまま返す(手抜き) + return memblock; + } else { + // サイズ拡大 + void *p = _mmalloc(size,file,line,func); + if(p != NULL) { + memcpy(p,memblock,old_size); + } + _mfree(memblock,file,line,func); + return p; + } } -char *_mstrdup(const char *p, const char *file, int line, const char *func) +char* _mstrdup(const char *p, const char *file, int line, const char *func ) { - if (p == NULL) { - return NULL; - } else { - size_t len = strlen(p); - char *string = (char *)_mmalloc(len + 1,file,line,func); - memcpy(string,p,len+1); - return string; - } + if(p == NULL) { + return NULL; + } else { + size_t len = strlen(p); + char *string = (char *)_mmalloc(len + 1,file,line,func); + memcpy(string,p,len+1); + return string; + } } -void _mfree(void *ptr, const char *file, int line, const char *func) +void _mfree(void *ptr, const char *file, int line, const char *func ) { - struct unit_head *head; - - if (ptr == NULL) - return; - - head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long)); - if (head->size == 0) { - /* malloc() で直に確保された領域 */ - struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(long)); - if ( - *(long *)((char *)head_large + sizeof(struct unit_head_large) - sizeof(long) + head_large->size) - != 0xdeadbeaf) { - ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line); - } else { - head->size = 0xFFFF; - if (head_large->prev) { - head_large->prev->next = head_large->next; - } else { - unit_head_large_first = head_large->next; - } - if (head_large->next) { - head_large->next->prev = head_large->prev; - } - memmgr_usage_bytes -= head_large->size; + struct unit_head *head; + + if (ptr == NULL) + return; + + head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long)); + if(head->size == 0) { + /* malloc() で直に確保された領域 */ + struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(long)); + if( + *(long*)((char*)head_large + sizeof(struct unit_head_large) - sizeof(long) + head_large->size) + != 0xdeadbeaf) + { + ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line); + } else { + head->size = 0xFFFF; + if(head_large->prev) { + head_large->prev->next = head_large->next; + } else { + unit_head_large_first = head_large->next; + } + if(head_large->next) { + head_large->next->prev = head_large->prev; + } + memmgr_usage_bytes -= head_large->size; #ifdef DEBUG_MEMMGR - // set freed memory to 0xfd - memset(ptr, 0xfd, head_large->size); + // set freed memory to 0xfd + memset(ptr, 0xfd, head_large->size); #endif - FREE(head_large,file,line,func); - } - } else { - /* ユニット解放 */ - struct block *block = head->block; - if ((char *)head - (char *)block > sizeof(struct block)) { - ShowError("Memory manager: args of aFree 0x%p is invalid pointer %s line %d\n", ptr, file, line); - } else if (head->block == NULL) { - ShowError("Memory manager: args of aFree 0x%p is freed pointer %s:%d@%s\n", ptr, file, line, func); - } else if (*(long *)((char *)head + sizeof(struct unit_head) - sizeof(long) + head->size) != 0xdeadbeaf) { - ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line); - } else { - memmgr_usage_bytes -= head->size; - head->block = NULL; + FREE(head_large,file,line,func); + } + } else { + /* ユニット解放 */ + struct block *block = head->block; + if( (char*)head - (char*)block > sizeof(struct block) ) { + ShowError("Memory manager: args of aFree 0x%p is invalid pointer %s line %d\n", ptr, file, line); + } else if(head->block == NULL) { + ShowError("Memory manager: args of aFree 0x%p is freed pointer %s:%d@%s\n", ptr, file, line, func); + } else if(*(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + head->size) != 0xdeadbeaf) { + ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line); + } else { + memmgr_usage_bytes -= head->size; + head->block = NULL; #ifdef DEBUG_MEMMGR - memset(ptr, 0xfd, block->unit_size - sizeof(struct unit_head) + sizeof(long)); - head->file = file; - head->line = line; + memset(ptr, 0xfd, block->unit_size - sizeof(struct unit_head) + sizeof(long) ); + head->file = file; + head->line = line; #endif - memmgr_assert(block->unit_used > 0); - if (--block->unit_used == 0) { - /* ブロックの解放 */ - block_free(block); - } else { - if (block->unfill_prev == NULL) { - // unfill リストに追加 - if (hash_unfill[ block->unit_hash ]) { - hash_unfill[ block->unit_hash ]->unfill_prev = block; - } - block->unfill_prev = &block_head; - block->unfill_next = hash_unfill[ block->unit_hash ]; - hash_unfill[ block->unit_hash ] = block; - } - head->size = block->unit_unfill; - block->unit_unfill = (unsigned short)(((uintptr_t)head - (uintptr_t)block->data) / block->unit_size); - } - } - } + memmgr_assert( block->unit_used > 0 ); + if(--block->unit_used == 0) { + /* ブロックの解放 */ + block_free(block); + } else { + if( block->unfill_prev == NULL) { + // unfill リストに追加 + if( hash_unfill[ block->unit_hash ] ) { + hash_unfill[ block->unit_hash ]->unfill_prev = block; + } + block->unfill_prev = &block_head; + block->unfill_next = hash_unfill[ block->unit_hash ]; + hash_unfill[ block->unit_hash ] = block; + } + head->size = block->unit_unfill; + block->unit_unfill = (unsigned short)(((uintptr_t)head - (uintptr_t)block->data) / block->unit_size); + } + } + } } /* ブロックを確保する */ -static struct block *block_malloc(unsigned short hash) { - int i; - struct block *p; - if (hash_unfill[0] != NULL) { - /* ブロック用の領域は確保済み */ - p = hash_unfill[0]; - hash_unfill[0] = hash_unfill[0]->unfill_next; - } else { - /* ブロック用の領域を新たに確保する */ - p = (struct block *)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__); - if (p == NULL) { - ShowFatalError("Memory manager::block_alloc failed.\n"); - exit(EXIT_FAILURE); - } - - if (block_first == NULL) { - /* 初回確保 */ - block_first = p; - } else { - block_last->block_next = p; - } - block_last = &p[BLOCK_ALLOC - 1]; - block_last->block_next = NULL; - /* ブロックを連結させる */ - for (i=0; i<BLOCK_ALLOC; i++) { - if (i != 0) { - // p[0] はこれから使うのでリンクには加えない - p[i].unfill_next = hash_unfill[0]; - hash_unfill[0] = &p[i]; - p[i].unfill_prev = NULL; - p[i].unit_used = 0; - } - if (i != BLOCK_ALLOC -1) { - p[i].block_next = &p[i+1]; - } - } - } - - // unfill に追加 - memmgr_assert(hash_unfill[ hash ] == NULL); - hash_unfill[ hash ] = p; - p->unfill_prev = &block_head; - p->unfill_next = NULL; - p->unit_size = (unsigned short)(hash2size(hash) + sizeof(struct unit_head)); - p->unit_hash = hash; - p->unit_count = BLOCK_DATA_SIZE / p->unit_size; - p->unit_used = 0; - p->unit_unfill = 0xFFFF; - p->unit_maxused = 0; +static struct block* block_malloc(unsigned short hash) +{ + int i; + struct block *p; + if(hash_unfill[0] != NULL) { + /* ブロック用の領域は確保済み */ + p = hash_unfill[0]; + hash_unfill[0] = hash_unfill[0]->unfill_next; + } else { + /* ブロック用の領域を新たに確保する */ + p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__ ); + if(p == NULL) { + ShowFatalError("Memory manager::block_alloc failed.\n"); + exit(EXIT_FAILURE); + } + + if(block_first == NULL) { + /* 初回確保 */ + block_first = p; + } else { + block_last->block_next = p; + } + block_last = &p[BLOCK_ALLOC - 1]; + block_last->block_next = NULL; + /* ブロックを連結させる */ + for(i=0;i<BLOCK_ALLOC;i++) { + if(i != 0) { + // p[0] はこれから使うのでリンクには加えない + p[i].unfill_next = hash_unfill[0]; + hash_unfill[0] = &p[i]; + p[i].unfill_prev = NULL; + p[i].unit_used = 0; + } + if(i != BLOCK_ALLOC -1) { + p[i].block_next = &p[i+1]; + } + } + } + + // unfill に追加 + memmgr_assert(hash_unfill[ hash ] == NULL); + hash_unfill[ hash ] = p; + p->unfill_prev = &block_head; + p->unfill_next = NULL; + p->unit_size = (unsigned short)(hash2size( hash ) + sizeof(struct unit_head)); + p->unit_hash = hash; + p->unit_count = BLOCK_DATA_SIZE / p->unit_size; + p->unit_used = 0; + p->unit_unfill = 0xFFFF; + p->unit_maxused = 0; #ifdef DEBUG_MEMMGR - memset(p->data, 0xfd, sizeof(p->data)); + memset( p->data, 0xfd, sizeof(p->data) ); #endif - return p; + return p; } -static void block_free(struct block *p) +static void block_free(struct block* p) { - if (p->unfill_prev) { - if (p->unfill_prev == &block_head) { - hash_unfill[ p->unit_hash ] = p->unfill_next; - } else { - p->unfill_prev->unfill_next = p->unfill_next; - } - if (p->unfill_next) { - p->unfill_next->unfill_prev = p->unfill_prev; - } - p->unfill_prev = NULL; - } - - p->unfill_next = hash_unfill[0]; - hash_unfill[0] = p; + if( p->unfill_prev ) { + if( p->unfill_prev == &block_head) { + hash_unfill[ p->unit_hash ] = p->unfill_next; + } else { + p->unfill_prev->unfill_next = p->unfill_next; + } + if( p->unfill_next ) { + p->unfill_next->unfill_prev = p->unfill_prev; + } + p->unfill_prev = NULL; + } + + p->unfill_next = hash_unfill[0]; + hash_unfill[0] = p; } -size_t memmgr_usage(void) +size_t memmgr_usage (void) { - return memmgr_usage_bytes / 1024; + return memmgr_usage_bytes / 1024; } #ifdef LOG_MEMMGR static char memmer_logfile[128]; static FILE *log_fp; -static void memmgr_log(char *buf) +static void memmgr_log (char *buf) { - if (!log_fp) { - time_t raw; - struct tm *t; - - log_fp = fopen(memmer_logfile,"at"); - if (!log_fp) log_fp = stdout; - - time(&raw); - t = localtime(&raw); - fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (Revision %s).\n", - (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, get_svn_revision()); - } - fprintf(log_fp, "%s", buf); - return; + if( !log_fp ) + { + time_t raw; + struct tm* t; + + log_fp = fopen(memmer_logfile,"at"); + if (!log_fp) log_fp = stdout; + + time(&raw); + t = localtime(&raw); + fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (Revision %s).\n", + (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, get_svn_revision()); + } + fprintf(log_fp, "%s", buf); + return; } #endif /* LOG_MEMMGR */ @@ -545,105 +553,107 @@ static void memmgr_log(char *buf) /// /// @param ptr Pointer to the memory /// @return true if the memory is active -bool memmgr_verify(void *ptr) +bool memmgr_verify(void* ptr) { - struct block *block = block_first; - struct unit_head_large *large = unit_head_large_first; - - if (ptr == NULL) - return false;// never valid - - // search small blocks - while (block) { - if ((char *)ptr >= (char *)block && (char *)ptr < ((char *)block) + sizeof(struct block)) { - // found memory block - if (block->unit_used && (char *)ptr >= block->data) { - // memory block is being used and ptr points to a sub-unit - size_t i = (size_t)((char *)ptr - block->data)/block->unit_size; - struct unit_head *head = block2unit(block, i); - if (i < block->unit_maxused && head->block != NULL) { - // memory unit is allocated, check if ptr points to the usable part - return ((char *)ptr >= ((char *)head) + sizeof(struct unit_head) - sizeof(long) - && (char *)ptr < ((char *)head) + sizeof(struct unit_head) - sizeof(long) + head->size); - } - } - return false; - } - block = block->block_next; - } - - // search large blocks - while (large) { - if ((char *)ptr >= (char *)large && (char *)ptr < ((char *)large) + large->size) { - // found memory block, check if ptr points to the usable part - return ((char *)ptr >= ((char *)large) + sizeof(struct unit_head_large) - sizeof(long) - && (char *)ptr < ((char *)large) + sizeof(struct unit_head_large) - sizeof(long) + large->size); - } - large = large->next; - } - return false; + struct block* block = block_first; + struct unit_head_large* large = unit_head_large_first; + + if( ptr == NULL ) + return false;// never valid + + // search small blocks + while( block ) + { + if( (char*)ptr >= (char*)block && (char*)ptr < ((char*)block) + sizeof(struct block) ) + {// found memory block + if( block->unit_used && (char*)ptr >= block->data ) + {// memory block is being used and ptr points to a sub-unit + size_t i = (size_t)((char*)ptr - block->data)/block->unit_size; + struct unit_head* head = block2unit(block, i); + if( i < block->unit_maxused && head->block != NULL ) + {// memory unit is allocated, check if ptr points to the usable part + return ( (char*)ptr >= ((char*)head) + sizeof(struct unit_head) - sizeof(long) + && (char*)ptr < ((char*)head) + sizeof(struct unit_head) - sizeof(long) + head->size ); + } + } + return false; + } + block = block->block_next; + } + + // search large blocks + while( large ) + { + if( (char*)ptr >= (char*)large && (char*)ptr < ((char*)large) + large->size ) + {// found memory block, check if ptr points to the usable part + return ( (char*)ptr >= ((char*)large) + sizeof(struct unit_head_large) - sizeof(long) + && (char*)ptr < ((char*)large) + sizeof(struct unit_head_large) - sizeof(long) + large->size ); + } + large = large->next; + } + return false; } -static void memmgr_final(void) +static void memmgr_final (void) { - struct block *block = block_first; - struct unit_head_large *large = unit_head_large_first; + struct block *block = block_first; + struct unit_head_large *large = unit_head_large_first; #ifdef LOG_MEMMGR - int count = 0; + int count = 0; #endif /* LOG_MEMMGR */ - while (block) { - if (block->unit_used) { - int i; - for (i = 0; i < block->unit_maxused; i++) { - struct unit_head *head = block2unit(block, i); - if (head->block != NULL) { - char *ptr = (char *)head + sizeof(struct unit_head) - sizeof(long); + while (block) { + if (block->unit_used) { + int i; + for (i = 0; i < block->unit_maxused; i++) { + struct unit_head *head = block2unit(block, i); + if(head->block != NULL) { + char* ptr = (char *)head + sizeof(struct unit_head) - sizeof(long); #ifdef LOG_MEMMGR - char buf[1024]; - sprintf(buf, - "%04d : %s line %d size %lu address 0x%p\n", ++count, - head->file, head->line, (unsigned long)head->size, ptr); - memmgr_log(buf); + char buf[1024]; + sprintf (buf, + "%04d : %s line %d size %lu address 0x%p\n", ++count, + head->file, head->line, (unsigned long)head->size, ptr); + memmgr_log (buf); #endif /* LOG_MEMMGR */ - // get block pointer and free it [celest] - _mfree(ptr, ALC_MARK); - } - } - } - block = block->block_next; - } - - while (large) { - struct unit_head_large *large2; + // get block pointer and free it [celest] + _mfree(ptr, ALC_MARK); + } + } + } + block = block->block_next; + } + + while(large) { + struct unit_head_large *large2; #ifdef LOG_MEMMGR - char buf[1024]; - sprintf(buf, - "%04d : %s line %d size %lu address 0x%p\n", ++count, - large->unit_head.file, large->unit_head.line, (unsigned long)large->size, &large->unit_head.checksum); - memmgr_log(buf); + char buf[1024]; + sprintf (buf, + "%04d : %s line %d size %lu address 0x%p\n", ++count, + large->unit_head.file, large->unit_head.line, (unsigned long)large->size, &large->unit_head.checksum); + memmgr_log (buf); #endif /* LOG_MEMMGR */ - large2 = large->next; - FREE(large,file,line,func); - large = large2; - } + large2 = large->next; + FREE(large,file,line,func); + large = large2; + } #ifdef LOG_MEMMGR - if (count == 0) { - ShowInfo("Memory manager: No memory leaks found.\n"); - } else { - ShowWarning("Memory manager: Memory leaks found and fixed.\n"); - fclose(log_fp); - } + if(count == 0) { + ShowInfo("Memory manager: No memory leaks found.\n"); + } else { + ShowWarning("Memory manager: Memory leaks found and fixed.\n"); + fclose(log_fp); + } #endif /* LOG_MEMMGR */ } -static void memmgr_init(void) +static void memmgr_init (void) { #ifdef LOG_MEMMGR - sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME); - ShowStatus("Memory manager initialised: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile); - memset(hash_unfill, 0, sizeof(hash_unfill)); + sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME); + ShowStatus("Memory manager initialised: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile); + memset(hash_unfill, 0, sizeof(hash_unfill)); #endif /* LOG_MEMMGR */ } #endif /* USE_MEMMGR */ @@ -658,51 +668,51 @@ static void memmgr_init(void) /// Tests the memory for errors and memory leaks. void malloc_memory_check(void) { - MEMORY_CHECK(); + MEMORY_CHECK(); } /// Returns true if a pointer is valid. /// The check is best-effort, false positives are possible. -bool malloc_verify_ptr(void *ptr) +bool malloc_verify_ptr(void* ptr) { #ifdef USE_MEMMGR - return memmgr_verify(ptr) && MEMORY_VERIFY(ptr); + return memmgr_verify(ptr) && MEMORY_VERIFY(ptr); #else - return MEMORY_VERIFY(ptr); + return MEMORY_VERIFY(ptr); #endif } -size_t malloc_usage(void) +size_t malloc_usage (void) { #ifdef USE_MEMMGR - return memmgr_usage(); + return memmgr_usage (); #else - return MEMORY_USAGE(); + return MEMORY_USAGE(); #endif } -void malloc_final(void) +void malloc_final (void) { #ifdef USE_MEMMGR - memmgr_final(); + memmgr_final (); #endif - MEMORY_CHECK(); + MEMORY_CHECK(); } -void malloc_init(void) +void malloc_init (void) { #if defined(DMALLOC) && defined(CYGWIN) - // http://dmalloc.com/docs/latest/online/dmalloc_19.html - dmalloc_debug_setup(getenv("DMALLOC_OPTIONS")); + // http://dmalloc.com/docs/latest/online/dmalloc_19.html + dmalloc_debug_setup(getenv("DMALLOC_OPTIONS")); #endif #ifdef GCOLLECT - // don't garbage collect, only report inaccessible memory that was not deallocated - GC_find_leak = 1; - GC_INIT(); + // don't garbage collect, only report inaccessible memory that was not deallocated + GC_find_leak = 1; + GC_INIT(); #endif #ifdef USE_MEMMGR - memmgr_init(); + memmgr_init (); #endif } |