summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorcelest <celest@54d463be-8e91-2dee-dedb-b68131a5f0ec>2005-02-22 16:08:24 +0000
committercelest <celest@54d463be-8e91-2dee-dedb-b68131a5f0ec>2005-02-22 16:08:24 +0000
commitf65bf4bd28cd9240c889bfd2a1f4650d91760a2d (patch)
tree6730a4d5ca802cc2c4cdb128dca07f1e95cac0fb /src/common
parent6b0b62a5b2a9d85f60afe4fe048403101bd8f39d (diff)
downloadhercules-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/Makefile34
-rw-r--r--src/common/core.c74
-rw-r--r--src/common/db.c20
-rw-r--r--src/common/db.h10
-rw-r--r--src/common/grfio.c55
-rw-r--r--src/common/malloc.c484
-rw-r--r--src/common/malloc.h8
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