diff options
author | celest <celest@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2005-02-22 16:08:24 +0000 |
---|---|---|
committer | celest <celest@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2005-02-22 16:08:24 +0000 |
commit | f65bf4bd28cd9240c889bfd2a1f4650d91760a2d (patch) | |
tree | 6730a4d5ca802cc2c4cdb128dca07f1e95cac0fb /src/common | |
parent | 6b0b62a5b2a9d85f60afe4fe048403101bd8f39d (diff) | |
download | hercules-f65bf4bd28cd9240c889bfd2a1f4650d91760a2d.tar.gz hercules-f65bf4bd28cd9240c889bfd2a1f4650d91760a2d.tar.bz2 hercules-f65bf4bd28cd9240c889bfd2a1f4650d91760a2d.tar.xz hercules-f65bf4bd28cd9240c889bfd2a1f4650d91760a2d.zip |
* Corrected Spiral Pierce's hits in the skill_db
* Moved /common/*.o into a obj folder when compiling
* Updated core and map server to jA 1094~1115
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/branches/stable@1162 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/Makefile | 34 | ||||
-rw-r--r-- | src/common/core.c | 74 | ||||
-rw-r--r-- | src/common/db.c | 20 | ||||
-rw-r--r-- | src/common/db.h | 10 | ||||
-rw-r--r-- | src/common/grfio.c | 55 | ||||
-rw-r--r-- | src/common/malloc.c | 484 | ||||
-rw-r--r-- | src/common/malloc.h | 8 |
7 files changed, 610 insertions, 75 deletions
diff --git a/src/common/Makefile b/src/common/Makefile index eaa7205d2..c387c2e01 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -1,15 +1,23 @@ -txt sql all: core.o socket.o timer.o grfio.o db.o lock.o nullpo.o malloc.o showmsg.o - -core.o: core.c core.h showmsg.h -socket.o: socket.c socket.h mmo.h showmsg.h -timer.o: timer.c timer.h showmsg.h -grfio.o: grfio.c grfio.h showmsg.h -db.o: db.c db.h showmsg.h -lock.o: lock.h showmsg.h -nullpo.o: nullpo.c nullpo.h showmsg.h -malloc.o: malloc.c malloc.h showmsg.h -showmsg.o: showmsg.c showmsg.h -strlib.o: strlib.c strlib.h utils.h +txt sql all: obj common + +obj: + mkdir obj + +common: obj/core.o obj/socket.o obj/timer.o obj/grfio.o obj/db.o obj/lock.o obj/nullpo.o obj/malloc.o obj/showmsg.o obj/strlib.o obj/utils.o + +obj/%.o: %.c + $(COMPILE.c) $(OUTPUT_OPTION) $< + +obj/core.o: core.c core.h showmsg.h +obj/socket.o: socket.c socket.h mmo.h showmsg.h +obj/timer.o: timer.c timer.h showmsg.h +obj/grfio.o: grfio.c grfio.h showmsg.h +obj/db.o: db.c db.h showmsg.h +obj/lock.o: lock.h showmsg.h +obj/nullpo.o: nullpo.c nullpo.h showmsg.h +obj/malloc.o: malloc.c malloc.h showmsg.h +obj/showmsg.o: showmsg.c showmsg.h +obj/strlib.o: strlib.c strlib.h utils.h clean: - rm -f *.o + rm -f *.o obj diff --git a/src/common/core.c b/src/common/core.c index fbd607080..016ade08d 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -9,10 +9,13 @@ #include <signal.h> #include <string.h> #ifdef DUMPSTACK -#include <execinfo.h> + #ifndef _WIN32 // HAVE_EXECINFO_H + #include <execinfo.h> + #endif #endif #include "../common/mmo.h" +#include "malloc.h" #include "core.h" #include "socket.h" #include "timer.h" @@ -92,44 +95,44 @@ static void sig_proc(int sn) * Dumps the stack using glibc's backtrace *----------------------------------------- */ -#ifdef DUMPSTACK static void sig_dump(int sn) { - FILE *fp; - void* array[20]; + #ifdef DUMPSTACK + FILE *fp; + void* array[20]; - char **stack; - size_t size; - int no = 0; - char tmp[256]; + char **stack; + size_t size; + int no = 0; + char tmp[256]; - // search for a usable filename - do { - sprintf(tmp,"save/stackdump_%04d.txt", ++no); - } while((fp = fopen(tmp,"r")) && (fclose(fp), no < 9999)); - // dump the trace into the file - if ((fp = fopen (tmp,"w")) != NULL) { + // search for a usable filename + do { + sprintf(tmp,"save/stackdump_%04d.txt", ++no); + } while((fp = fopen(tmp,"r")) && (fclose(fp), no < 9999)); + // dump the trace into the file + if ((fp = fopen (tmp,"w")) != NULL) { - fprintf(fp,"Exception: %s\n", strsignal(sn)); - fprintf(fp,"Stack trace:\n"); - size = backtrace (array, 20); - stack = backtrace_symbols (array, size); + fprintf(fp,"Exception: %s\n", strsignal(sn)); + fprintf(fp,"Stack trace:\n"); + size = backtrace (array, 20); + stack = backtrace_symbols (array, size); - for (no = 0; no < size; no++) { + for (no = 0; no < size; no++) { - fprintf(fp, "%s\n", stack[no]); + fprintf(fp, "%s\n", stack[no]); - } - fprintf(fp,"End of stack trace\n"); + } + fprintf(fp,"End of stack trace\n"); - fclose(fp); - free(stack); - } + fclose(fp); + free(stack); + } + #endif // When pass the signal to the system's default handler compat_signal(sn, SIG_DFL); raise(sn); } -#endif int get_svn_revision(char *svnentry) { // Warning: minor syntax checking char line[1024]; @@ -204,28 +207,20 @@ int main(int argc,char **argv) compat_signal(SIGPIPE,SIG_IGN); compat_signal(SIGTERM,sig_proc); compat_signal(SIGINT,sig_proc); - -#ifndef DUMPSTACK - // Signal to create coredumps by system when necessary (crash) - compat_signal(SIGSEGV, SIG_DFL); - compat_signal(SIGFPE, SIG_DFL); - compat_signal(SIGILL, SIG_DFL); - #ifndef _WIN32 - compat_signal(SIGBUS, SIG_DFL); - compat_signal(SIGTRAP, SIG_DFL); - #endif -#else + + // Signal to create coredumps by system when necessary (crash) compat_signal(SIGSEGV, sig_dump); compat_signal(SIGFPE, sig_dump); compat_signal(SIGILL, sig_dump); #ifndef _WIN32 compat_signal(SIGBUS, sig_dump); - compat_signal(SIGTRAP, SIG_DFL); + compat_signal(SIGTRAP, SIG_DFL); #endif -#endif display_title(); + do_init_memmgr(argv[0]); // 一番最初に実行する必要がある + tick_ = time(0); do_init(argc,argv); @@ -234,5 +229,6 @@ int main(int argc,char **argv) do_sendrecv(next); do_parsepacket(); } + return 0; } diff --git a/src/common/db.c b/src/common/db.c index 12d54176c..9f2c75a68 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -65,7 +65,7 @@ static unsigned int strdb_hash(struct dbt* table,void* a) return h; } -struct dbt* strdb_init(int maxlen) +struct dbt* strdb_init_(int maxlen,const char *file,int line) { int i; struct dbt* table; @@ -77,6 +77,9 @@ struct dbt* strdb_init(int maxlen) table->maxlen=maxlen; for(i=0;i<HASH_SIZE;i++) table->ht[i]=NULL; + table->alloc_file = file; + table->alloc_line = line; + table->item_count = 0; return table; } @@ -98,7 +101,7 @@ static unsigned int numdb_hash(struct dbt* table,void* a) return (unsigned int)a; } -struct dbt* numdb_init(void) +struct dbt* numdb_init_(const char *file,int line) { int i; struct dbt* table; @@ -110,6 +113,9 @@ struct dbt* numdb_init(void) table->maxlen=sizeof(int); for(i=0;i<HASH_SIZE;i++) table->ht[i]=NULL; + table->alloc_file = file; + table->alloc_line = line; + table->item_count = 0; return table; } @@ -400,6 +406,7 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data) db_rebalance(p,&table->ht[hash]); } } + table->item_count++; return p; } @@ -428,12 +435,14 @@ void* db_erase(struct dbt *table,void* key) #else aFree(p); #endif + table->item_count--; return data; } void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) { int i,sp; + int count = 0; // red-black treeなので64個stackがあれば2^32個ノードまで大丈夫 struct dbn *p,*pn,*stack[64]; va_list ap; @@ -449,6 +458,7 @@ void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) // printf("Warning: no data for key %d in db_foreach (db.c) !\n",(int)p->key); //} else { func(p->key, p->data, ap); + count++; //} if((pn=p->left)!=NULL){ if(p->right){ @@ -466,6 +476,12 @@ void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) } } } + if(count != table->item_count) { + printf( + "db_foreach : data lost %d of %d item(s) allocated from %s line %d\n", + table->item_count - count,count,table->alloc_file,table->alloc_line + ); + } va_end(ap); } diff --git a/src/common/db.h b/src/common/db.h index ea9aceab0..c31f5bfaa 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -22,6 +22,9 @@ struct dbt { void (*release)(struct dbn*,int which); int maxlen; struct dbn *ht[HASH_SIZE]; + int item_count; // vf? + const char* alloc_file; // DB?t@C + int alloc_line; // DB?s }; #define strdb_search(t,k) db_search((t),(void*)(k)) @@ -34,9 +37,12 @@ struct dbt { #define numdb_erase(t,k) db_erase ((t),(void*)(k)) #define numdb_foreach db_foreach #define numdb_final db_final +#define strdb_init(a) strdb_init_(a,__FILE__,__LINE__) +#define numdb_init() numdb_init_(__FILE__,__LINE__) + +struct dbt* strdb_init_(int maxlen,const char *file,int line); +struct dbt* numdb_init_(const char *file,int line); -struct dbt* strdb_init(int maxlen); -struct dbt* numdb_init(void); void* db_search(struct dbt *table,void* key); void* db_search2(struct dbt *table, const char *key); // [MouseJstr] struct dbn* db_insert(struct dbt *table,void* key,void* data); diff --git a/src/common/grfio.c b/src/common/grfio.c index 0c628d163..224ea909e 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -32,21 +32,36 @@ #include "malloc.h" #ifdef _WIN32 - #include <windows.h> - #include "../lib/zlib_win32.h" - HINSTANCE zlib_dll; - #define zlib_inflateInit(strm) zlib_inflateInit_((strm),ZLIB_VERSION, sizeof(z_stream)) - #define zlib_deflateInit(strm, level) zlib_deflateInit_((strm),(level),ZLIB_VERSION,sizeof(z_stream)) - - int (WINAPI* zlib_inflateInit_) (z_streamp strm, const char *version, int stream_size); - int (WINAPI* zlib_inflate) (z_streamp strm, int flush); - int (WINAPI* zlib_inflateEnd) (z_streamp strm); - - int (WINAPI* zlib_deflateInit_) (z_streamp strm, int level, const char *version, int stream_size); - int (WINAPI* zlib_deflate) (z_streamp strm, int flush); - int (WINAPI* zlib_deflateEnd) (z_streamp strm); + #ifdef LOCALZLIB + #include "../lib/zlib/zlib.h" + #define zlib_inflateInit inflateInit + #define zlib_inflate inflate + #define zlib_inflateEnd inflateEnd + #define zlib_deflateInit deflateInit + #define zlib_deflate deflate + #define zlib_deflateEnd deflateEnd + #else + #include <windows.h> + #include "../lib/zlib_win32.h" + HINSTANCE zlib_dll; + #define zlib_inflateInit(strm) zlib_inflateInit_((strm),ZLIB_VERSION, sizeof(z_stream)) + #define zlib_deflateInit(strm, level) zlib_deflateInit_((strm),(level),ZLIB_VERSION,sizeof(z_stream)) + + int (WINAPI* zlib_inflateInit_) (z_streamp strm, const char *version, int stream_size); + int (WINAPI* zlib_inflate) (z_streamp strm, int flush); + int (WINAPI* zlib_inflateEnd) (z_streamp strm); + + int (WINAPI* zlib_deflateInit_) (z_streamp strm, int level, const char *version, int stream_size); + int (WINAPI* zlib_deflate) (z_streamp strm, int flush); + int (WINAPI* zlib_deflateEnd) (z_streamp strm); + #endif #else - #include <zlib.h> + #ifdef LOCALZLIB + #include "zlib/zlib.h" + #else + #include <zlib.h> + #endif + #define zlib_inflateInit inflateInit #define zlib_inflate inflate #define zlib_inflateEnd inflateEnd @@ -966,6 +981,16 @@ void grfio_final(void) } gentry_table = NULL; gentry_entrys = gentry_maxentry = 0; + +#ifdef _WIN32 + #ifndef LOCALZLIB + FreeLibrary(zlib_dll); + zlib_inflateInit_ = NULL; + zlib_inflate = NULL; + zlib_inflateEnd = NULL; + #endif +#endif + } /*========================================== @@ -979,6 +1004,7 @@ void grfio_init(char *fname) int result = 0, result2 = 0, result3 = 0, result4 = 0; #ifdef _WIN32 + #ifndef LOCALZLIB if(!zlib_dll) { zlib_dll = LoadLibrary("zlib.dll"); (FARPROC)zlib_inflateInit_ = GetProcAddress(zlib_dll,"inflateInit_"); @@ -992,6 +1018,7 @@ void grfio_init(char *fname) exit(1); } } + #endif #endif data_conf = fopen(fname, "r"); diff --git a/src/common/malloc.c b/src/common/malloc.c index 089a9db18..40c9f34bf 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -3,14 +3,25 @@ #include <string.h> #include "malloc.h" -#if !defined(DMALLOC) && !defined(GCOLLECT) && !defined(BCHECK) +#ifdef MEMWATCH +#include "memwatch.h" +#endif + +// 独自メモリマネージャを使用する場合、次のコメントを外してください。 +// #define USE_MEMMGR + +#if !defined(DMALLOC) && !defined(GCOLLECT) && !defined(BCHECK) && !defined(USE_MEMMGR) void* aMalloc_( size_t size, const char *file, int line, const char *func ) { void *ret; // printf("%s:%d: in func %s: malloc %d\n",file,line,func,size); +#ifdef MEMWATCH + ret=mwMalloc(size,file,line); +#else ret=malloc(size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: malloc error out of memory!\n",file,line,func); exit(1); @@ -23,7 +34,11 @@ void* aCalloc_( size_t num, size_t size, const char *file, int line, const char void *ret; // printf("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size); +#ifdef MEMWATCH + ret=mwCalloc(num,size,file,line); +#else ret=calloc(num,size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: calloc error out of memory!\n",file,line,func); exit(1); @@ -37,7 +52,11 @@ void* aRealloc_( void *p, size_t size, const char *file, int line, const char *f void *ret; // printf("%s:%d: in func %s: realloc %p %d\n",file,line,func,p,size); +#ifdef MEMWATCH + ret=mwRealloc(p,size,file,line); +#else ret=realloc(p,size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: realloc error out of memory!\n",file,line,func); exit(1); @@ -46,10 +65,39 @@ void* aRealloc_( void *p, size_t size, const char *file, int line, const char *f return ret; } +void* aStrdup_( const void *p, const char *file, int line, const char *func ) +{ + void *ret; + + // printf("%s:%d: in func %s: strdup %p\n",file,line,func,p); +#ifdef MEMWATCH + ret=mwStrdup(p,file,line); +#else + ret=strdup(p); +#endif + if(ret==NULL){ + printf("%s:%d: in func %s: strdup error out of memory!\n",file,line,func); + exit(1); + + } + return ret; +} + +void aFree_( void *p, const char *file, int line, const char *func ) +{ + // printf("%s:%d: in func %s: free %p\n",file,line,func,p); +#ifdef MEMWATCH + mwFree(p,file,line); +#else + free(p); #endif +} +int do_init_memmgr(const char* file) { + return 0; +} -#if defined(GCOLLECT) +#elif defined(GCOLLECT) void * _bcallocA(size_t size, size_t cnt) { void *ret = aMallocA(size * cnt); @@ -62,7 +110,6 @@ void * _bcalloc(size_t size, size_t cnt) { memset(ret, 0, size * cnt); return ret; } -#endif char * _bstrdup(const char *chr) { int len = strlen(chr); @@ -70,3 +117,434 @@ char * _bstrdup(const char *chr) { strcpy(ret, chr); return ret; } + +#elif defined(USE_MEMMGR) + +/* USE_MEMMGR */ + +/* + * メモリマネージャ + * malloc , free の処理を効率的に出来るようにしたもの。 + * 複雑な処理を行っているので、若干重くなるかもしれません。 + * + * データ構造など(説明下手ですいません^^; ) + * ・メモリを複数の「ブロック」に分けて、さらにブロックを複数の「ユニット」 + * に分けています。ユニットのサイズは、1ブロックの容量を複数個に均等配分 + * したものです。たとえば、1ユニット32KBの場合、ブロック1つは32Byteのユ + * ニットが、1024個集まって出来ていたり、64Byteのユニットが 512個集まって + * 出来ていたりします。(padding,unit_head を除く) + * + * ・ユニット同士はリンクリスト(block_prev,block_next) でつながり、同じサイ + * ズを持つユニット同士もリンクリスト(samesize_prev,samesize_nect) でつな + * がっています。それにより、不要となったメモリの再利用が効率的に行えます。 + */ + +/* ブロックに入るデータ量 */ +#define BLOCK_DATA_SIZE 80*1024 + +/* 一度に確保するブロックの数。 */ +#define BLOCK_ALLOC 32 + +/* ブロックのアライメント */ +#define BLOCK_ALIGNMENT 64 + +/* ブロック */ +struct block { + int block_no; /* ブロック番号 */ + struct block* block_prev; /* 前に確保した領域 */ + struct block* block_next; /* 次に確保した領域 */ + int samesize_no; /* 同じサイズの番号 */ + struct block* samesize_prev; /* 同じサイズの前の領域 */ + struct block* samesize_next; /* 同じサイズの次の領域 */ + int unit_size; /* ユニットのバイト数 0=未使用 */ + int unit_hash; /* ユニットのハッシュ */ + int unit_count; /* ユニットの数 */ + int unit_used; /* 使用済みユニット */ + char data[BLOCK_DATA_SIZE]; +}; + +struct unit_head { + struct block* block; + int size; + const char* file; + int line; +}; + +static struct block* block_first = NULL; +static struct block* block_last = NULL; +static struct block* block_unused = NULL; + +/* ユニットへのハッシュ。80KB/64Byte = 1280個 */ +static struct block* unit_first[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 最初 */ +static struct block* unit_unfill[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 埋まってない */ +static struct block* unit_last[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 最後 */ + +/* メモリを使い回せない領域用のデータ */ +struct unit_head_large { + 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(void); +static void block_free(struct block* p); +static void memmgr_info(void); + +void* aMalloc_(size_t size, const char *file, int line, const char *func ) { + int i; + struct block *block; + int size_hash = (size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT; + size = size_hash * BLOCK_ALIGNMENT; /* アライメントの倍数に切り上げ */ + + if(size == 0) { + return NULL; + } + + /* ブロック長を超える領域の確保には、malloc() を用いる */ + /* その際、unit_head.block に NULL を代入して区別する */ + if(size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { +#ifdef MEMWATCH + struct unit_head_large* p = (struct unit_head_large*)mwMalloc(sizeof(struct unit_head_large) + size,file,line); +#else + struct unit_head_large* p = (struct unit_head_large*)malloc(sizeof(struct unit_head_large) + size); +#endif + if(p != NULL) { + p->unit_head.block = NULL; + p->unit_head.size = size; + p->unit_head.file = file; + p->unit_head.line = line; + if(unit_head_large_first == NULL) { + unit_head_large_first = p; + p->next = NULL; + p->prev = NULL; + } else { + unit_head_large_first->prev = p; + p->prev = NULL; + p->next = unit_head_large_first; + unit_head_large_first = p; + } + return (char *)p + sizeof(struct unit_head_large); + } else { + printf("MEMMGR::memmgr_alloc failed.\n"); + exit(1); + } + } + + /* 同一サイズのブロックが確保されていない時、新たに確保する */ + if(unit_unfill[size_hash] == NULL) { + block = block_malloc(); + if(unit_first[size_hash] == NULL) { + /* 初回確保 */ + unit_first[size_hash] = block; + unit_last[size_hash] = block; + block->samesize_no = 0; + block->samesize_prev = NULL; + block->samesize_next = NULL; + } else { + /* 連結作業 */ + unit_last[size_hash]->samesize_next = block; + block->samesize_no = unit_last[size_hash]->samesize_no + 1; + block->samesize_prev = unit_last[size_hash]; + block->samesize_next = NULL; + unit_last[size_hash] = block; + } + unit_unfill[size_hash] = block; + block->unit_size = size + sizeof(struct unit_head); + block->unit_count = BLOCK_DATA_SIZE / block->unit_size; + block->unit_used = 0; + block->unit_hash = size_hash; + /* 未使用Flagを立てる */ + for(i=0;i<block->unit_count;i++) { + ((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL; + } + } + /* ユニット使用個数加算 */ + block = unit_unfill[size_hash]; + block->unit_used++; + + /* ユニット内を全て使い果たした */ + if(block->unit_count == block->unit_used) { + do { + unit_unfill[size_hash] = unit_unfill[size_hash]->samesize_next; + } while( + unit_unfill[size_hash] != NULL && + unit_unfill[size_hash]->unit_count == unit_unfill[size_hash]->unit_used + ); + } + + /* ブロックの中の空きユニット捜索 */ + for(i=0;i<block->unit_count;i++) { + struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); + if(head->block == NULL) { + head->block = block; + head->size = size; + head->line = line; + head->file = file; + return (char *)head + sizeof(struct unit_head); + } + } + // ここに来てはいけない。 + printf("MEMMGR::memmgr_malloc() serious error.\n"); + memmgr_info(); + exit(1); + return NULL; +}; + +void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func ) { + void *p = aMalloc_(num * size,file,line,func); + memset(p,0,num * size); + return p; +} + +void* aRealloc_(void *memblock, size_t size, const char *file, int line, const char *func ) { + size_t old_size; + if(memblock == NULL) { + return aMalloc_(size,file,line,func); + } + + old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head)))->size; + if(old_size > size) { + // サイズ縮小 -> そのまま返す(手抜き) + return memblock; + } else { + // サイズ拡大 + void *p = aMalloc_(size,file,line,func); + if(p != NULL) { + memcpy(p,memblock,old_size); + } + aFree_(memblock,file,line,func); + return p; + } +} + +void* aStrdup_(const void* string, const char *file, int line, const char *func ) { + if(string == NULL) { + return NULL; + } else { + int len = strlen(string); + char *p = (char *)aMalloc_(len + 1,file,line,func); + memcpy(p,string,len+1); + return p; + } +} + +void aFree_(void *ptr, const char *file, int line, const char *func ) { + struct unit_head *head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head)); + if(ptr == NULL) { + return; + } else if(head->block == NULL && head->size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { + /* malloc() で直に確保された領域 */ + struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large)); + 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; + } + free(head_large); + return; + } else { + /* ユニット解放 */ + struct block *block = head->block; + if(head->block == NULL) { + printf("memmgr: args of aFree is freed pointer %s line %d\n",file,line); + } else { + head->block = NULL; + if(--block->unit_used == 0) { + /* ブロックの解放 */ + if(unit_unfill[block->unit_hash] == block) { + /* 空きユニットに指定されている */ + do { + unit_unfill[block->unit_hash] = unit_unfill[block->unit_hash]->samesize_next; + } while( + unit_unfill[block->unit_hash] != NULL && + unit_unfill[block->unit_hash]->unit_count == unit_unfill[block->unit_hash]->unit_used + ); + } + if(block->samesize_prev == NULL && block->samesize_next == NULL) { + /* 独立ブロックの解放 */ + unit_first[block->unit_hash] = NULL; + unit_last[block->unit_hash] = NULL; + unit_unfill[block->unit_hash] = NULL; + } else if(block->samesize_prev == NULL) { + /* 先頭ブロックの解放 */ + unit_first[block->unit_hash] = block->samesize_next; + (block->samesize_next)->samesize_prev = NULL; + } else if(block->samesize_next == NULL) { + /* 末端ブロックの解放 */ + unit_last[block->unit_hash] = block->samesize_prev; + (block->samesize_prev)->samesize_next = NULL; + } else { + /* 中間ブロックの解放 */ + (block->samesize_next)->samesize_prev = block->samesize_prev; + (block->samesize_prev)->samesize_next = block->samesize_next; + } + block_free(block); + } else { + /* 空きユニットの再設定 */ + if( + unit_unfill[block->unit_hash] == NULL || + unit_unfill[block->unit_hash]->samesize_no > block->samesize_no + ) { + unit_unfill[block->unit_hash] = block; + } + } + } + } +} + +/* 現在の状況を表示する */ +static void memmgr_info(void) { + int i; + struct block *p; + printf("** Memory Maneger Information **\n"); + if(block_first == NULL) { + printf("Uninitialized.\n"); + return; + } + printf( + "Blocks: %04u , BlockSize: %06u Byte , Used: %08uKB\n", + block_last->block_no+1,sizeof(struct block), + (block_last->block_no+1) * sizeof(struct block) / 1024 + ); + p = block_first; + for(i=0;i<=block_last->block_no;i++) { + printf(" Block #%04u : ",p->block_no); + if(p->unit_size == 0) { + printf("unused.\n"); + } else { + printf( + "size: %05u byte. used: %04u/%04u prev:", + p->unit_size - sizeof(struct unit_head),p->unit_used,p->unit_count + ); + if(p->samesize_prev == NULL) { + printf("NULL"); + } else { + printf("%04u",(p->samesize_prev)->block_no); + } + printf(" next:"); + if(p->samesize_next == NULL) { + printf("NULL"); + } else { + printf("%04u",(p->samesize_next)->block_no); + } + printf("\n"); + } + p = p->block_next; + } +} + +/* ブロックを確保する */ +static struct block* block_malloc(void) { + if(block_unused != NULL) { + /* ブロック用の領域は確保済み */ + struct block* ret = block_unused; + do { + block_unused = block_unused->block_next; + } while(block_unused != NULL && block_unused->unit_size != 0); + return ret; + } else { + /* ブロック用の領域を新たに確保する */ + int i; + int block_no; + struct block* p = (struct block *)calloc(sizeof(struct block),BLOCK_ALLOC); + if(p == NULL) { + printf("MEMMGR::block_alloc failed.\n"); + exit(1); + } + if(block_first == NULL) { + /* 初回確保 */ + block_no = 0; + block_first = p; + } else { + block_no = block_last->block_no + 1; + block_last->block_next = p; + p->block_prev = block_last; + } + block_last = &p[BLOCK_ALLOC - 1]; + /* ブロックを連結させる */ + for(i=0;i<BLOCK_ALLOC;i++) { + if(i != 0) { + p[i].block_prev = &p[i-1]; + } + if(i != BLOCK_ALLOC -1) { + p[i].block_next = &p[i+1]; + } + p[i].block_no = block_no + i; + } + + /* 未使用ブロックへのポインタを更新 */ + block_unused = &p[1]; + p->unit_size = 1; + return p; + } +} + +static void block_free(struct block* p) { + /* free() せずに、未使用フラグを付けるだけ */ + p->unit_size = 0; + /* 未使用ポインターを更新する */ + if(block_unused == NULL) { + block_unused = p; + } else if(block_unused->block_no > p->block_no) { + block_unused = p; + } +} + +static char memmer_logfile[128]; + +static FILE* memmgr_log(void) { + FILE *fp = fopen(memmer_logfile,"w"); + if(!fp) { fp = stdout; } + fprintf(fp,"memmgr: memory leaks found\n"); + return fp; +} + +static void memmer_exit(void) { + FILE *fp = NULL; + int i; + int count = 0; + struct block *block = block_first; + struct unit_head_large *large = unit_head_large_first; + while(block) { + if(block->unit_size) { + if(!fp) { fp = memmgr_log(); } + for(i=0;i<block->unit_count;i++) { + struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); + if(head->block != NULL) { + fprintf( + fp,"%04d : %s line %d size %d\n",++count, + head->file,head->line,head->size + ); + } + } + } + block = block->block_next; + } + while(large) { + if(!fp) { fp = memmgr_log(); } + fprintf( + fp,"%04d : %s line %d size %d\n",++count, + large->unit_head.file, + large->unit_head.line,large->unit_head.size + ); + large = large->next; + } + if(!fp) { + printf("memmgr: no memory leaks found.\n"); + } else { + printf("memmgr: memory leaks found.\n"); + } +} + +int do_init_memmgr(const char* file) { + sprintf(memmer_logfile,"%s.log",file); + atexit(memmer_exit); + printf("memmgr: initialised: %s\n",memmer_logfile); + return 0; +} + +#endif diff --git a/src/common/malloc.h b/src/common/malloc.h index d90665487..45451c9e0 100644 --- a/src/common/malloc.h +++ b/src/common/malloc.h @@ -59,15 +59,19 @@ void* aMalloc_( 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* aRealloc_( void *p, size_t size, const char *file, int line, const char *func ); + void aFree_( void *p, const char *file, int line, const char *func ); + void* aStrdup_( const void *p, const char *file, int line, const char *func ); # define aMalloc(n) aMalloc_(n,ALC_MARK) # define aMallocA(n) aMalloc_(n,ALC_MARK) # define aCalloc(m,n) aCalloc_(m,n,ALC_MARK) # define aCallocA(m,n) aCalloc_(m,n,ALC_MARK) # define aRealloc(p,n) aRealloc_(p,n,ALC_MARK) -# define aFree(ptr) free(ptr) -# define aStrdup(ptr) strdup(ptr) +# define aStrdup(p) aStrdup_(p,ALC_MARK) +# define aFree(p) do { aFree_(p,ALC_MARK); if(p != NULL) { p = NULL; } } while(0) #endif +int do_init_memmgr(const char* file); + #endif |