Explorar o código

* Fixed alot of memory leaks
* Added stray memory cleaning routine to db.c

git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/stable@1275 54d463be-8e91-2dee-dedb-b68131a5f0ec

celest %!s(int64=20) %!d(string=hai) anos
pai
achega
91fb421a67

+ 2 - 0
Changelog-SVN.txt

@@ -1,6 +1,8 @@
 Date	Added
 
 03/23
+	* Fixed alot of memory leaks [celest]
+	* Added stray memory cleaning routine to db.c [celest]
 	* Fixed some compile errors, sorry xP [celest]
 	* Corrected potion creation success chances, thanks to Avaj and DracoRPG
 	* Removed some unused potion creation code, thanks to DracoRPG

+ 4 - 8
src/char/char.c

@@ -22,6 +22,7 @@
 #include "socket.h"
 #include "timer.h"
 #include "mmo.h"
+#include "db.h"
 #include "version.h"
 #include "lock.h"
 #include "char.h"
@@ -630,11 +631,6 @@ int mmo_char_init(void) {
 		printf("out of memory: mmo_char_init (calloc of char_dat).\n");
 		exit(1);
 	}
-	online_chars = (struct online_chars*)aCalloc(sizeof(struct online_chars) * 256, 1);
-	if (!online_chars) {
-		printf("out of memory: mmo_char_init (calloc of online_chars).\n");
-		exit(1);
-	}
 	for(i = 0; i < char_max; i++)
 	{
 		online_chars[i].char_id = -1;
@@ -3456,8 +3452,9 @@ void do_final(void) {
 	delete_session(login_fd);
 	delete_session(char_fd);
 
-	for(i = 0; i < fd_max; i++)
-		if(session[i] != NULL) aFree(session[i]);
+	inter_final();
+	exit_dbn();
+	timer_final();
 
 	char_log("----End of char-server (normal end with closing of all files)." RETCODE);
 }
@@ -3512,7 +3509,6 @@ int do_init(int argc, char **argv) {
 		online_chars[i].server = -1;
 	}
 
-
 	mmo_char_init();
 
 	update_online = time(NULL);

+ 19 - 1
src/char/int_guild.c

@@ -488,10 +488,28 @@ int inter_guild_init() {
 	return 0;
 }
 
+int castle_db_final (void *k, void *data, va_list ap)
+{
+	struct guild_castle *gc = data;
+	if (gc) aFree(gc);
+	return 0;
+}
+int guild_db_final (void *k, void *data, va_list ap)
+{
+	struct guild *g = data;
+	if (g) aFree(g);
+	return 0;
+}
+void inter_guild_final() {
+	numdb_final(castle_db, castle_db_final);
+	numdb_final(guild_db, guild_db_final);
+	return;
+}
+
 struct guild *inter_guild_search(int guild_id) {
 	struct guild *g;
 
-	g= (struct guild *) numdb_search(guild_db, guild_id);
+	g = (struct guild *) numdb_search(guild_db, guild_id);
 
 	return g;
 }

+ 1 - 0
src/char/int_guild.h

@@ -3,6 +3,7 @@
 #define _INT_GUILD_H_
 
 int inter_guild_init();
+void inter_guild_final();
 int inter_guild_save();
 int inter_guild_parse_frommap(int fd);
 struct guild *inter_guild_search(int guild_id);

+ 11 - 0
src/char/int_party.c

@@ -117,6 +117,17 @@ int inter_party_init() {
 	return 0;
 }
 
+int party_db_final (void *k, void *data, va_list ap) {
+	struct party *p = data;
+	if (p) aFree(p);
+	return 0;
+}
+void inter_party_final()
+{
+	numdb_final(party_db, party_db_final);
+	return;
+}
+
 // ƒp?ƒeƒB?ƒf?ƒ^‚̃Z?ƒu—p
 int inter_party_save_sub(void *key, void *data, va_list ap) {
 	char line[8192];

+ 1 - 0
src/char/int_party.h

@@ -3,6 +3,7 @@
 #define _INT_PARTY_H_
 
 int inter_party_init();
+void inter_party_final();
 int inter_party_save();
 
 int inter_party_parse_frommap(int fd);

+ 11 - 0
src/char/int_pet.c

@@ -109,6 +109,17 @@ int inter_pet_init()
 	return 0;
 }
 
+int pet_db_final (void *k, void *data, va_list ap) {
+	struct s_pet *p = data;
+	if (p) aFree(p);
+	return 0;
+}
+void inter_pet_final()
+{
+	numdb_final(pet_db, pet_db_final);
+	return;
+}
+
 int inter_pet_save_sub(void *key,void *data,va_list ap)
 {
 	char line[8192];

+ 1 - 0
src/char/int_pet.h

@@ -3,6 +3,7 @@
 #define _INT_PET_H_
 
 int inter_pet_init();
+void inter_pet_final();
 int inter_pet_save();
 int inter_pet_delete(int pet_id);
 

+ 16 - 0
src/char/int_storage.c

@@ -291,6 +291,22 @@ int inter_storage_init()
 	return 0;
 }
 
+int storage_db_final (void *k, void *data, va_list ap) {
+	struct storage *p = data;
+	if (p) aFree(p);
+	return 0;
+}
+int guild_storage_db_final (void *k, void *data, va_list ap) {
+	struct guild_storage *p = data;
+	if (p) aFree(p);
+	return 0;
+}
+void inter_storage_final() {
+	numdb_final(storage_db, storage_db_final);
+	numdb_final(guild_storage_db, guild_storage_db_final);
+	return;
+}
+
 int inter_storage_save_sub(void *key,void *data,va_list ap)
 {
 	char line[65536];

+ 1 - 0
src/char/int_storage.h

@@ -3,6 +3,7 @@
 #define _INT_STORAGE_H_
 
 int inter_storage_init();
+void inter_storage_final();
 int inter_storage_save();
 int inter_guild_storage_save();
 int inter_storage_delete(int account_id);

+ 23 - 0
src/char/inter.c

@@ -261,6 +261,29 @@ int inter_init(const char *file) {
 	return 0;
 }
 
+// finalize
+int accreg_db_final (void *k, void *data, va_list ap) {	
+	struct accreg *p = data;
+	if (p) aFree(p);
+	return 0;
+}
+int wis_db_final (void *k, void *data, va_list ap) {
+	struct WisData *p = data;
+	if (p) aFree(p);
+	return 0;
+}
+void inter_final() {
+	numdb_final(accreg_db, accreg_db_final);
+	numdb_final(wis_db, wis_db_final);
+
+	inter_party_final();
+	inter_guild_final();
+	inter_storage_final();
+	inter_pet_final();
+
+	return;
+}
+
 // ƒ}ƒbƒvƒT�[ƒo�[�Ú‘±
 int inter_mapif_init(int fd) {
 	inter_guild_mapif_init(fd);

+ 1 - 0
src/char/inter.h

@@ -3,6 +3,7 @@
 #define _INTER_H_
 
 int inter_init(const char *file);
+void inter_final();
 int inter_save();
 int inter_parse_frommap(int fd);
 int inter_mapif_init(int fd);

+ 9 - 0
src/char_sql/char.c

@@ -3134,6 +3134,12 @@ int char_lan_config_read(const char *lancfgName){
 	return 0;
 }
 
+static int char_db_final(void *key,void *data,va_list ap)
+{
+	struct mmo_charstatus *p = data;
+	if (p) aFree(p);
+	return 0;
+}
 void do_final(void) {
 	printf("Doing final stage...\n");
 	//mmo_char_sync();
@@ -3162,9 +3168,12 @@ void do_final(void) {
 
 	delete_session(login_fd);
 	delete_session(char_fd);
+	numdb_final(char_db_, char_db_final);
+	exit_dbn();
 
 	mysql_close(&mysql_handle);
 	mysql_close(&lmysql_handle);
+	timer_final();
 
 	printf("ok! all done...\n");
 }

+ 29 - 0
src/char_sql/int_guild.c

@@ -709,6 +709,35 @@ int inter_guild_sql_init()
 	return 0;
 }
 
+int guild_expcache_db_final (void *k, void *data, va_list ap) { return 0; }
+int guild_infoevent_db_final (void *k, void *data, va_list ap) { return 0; }
+int guild_castleinfoevent_db_final (void *k, void *data, va_list ap) { return 0; }
+int guild_db_final (void *k, void *data, va_list ap)
+{
+	struct guild *g = data;
+	if (g) aFree(g);
+	return 0;
+}
+int castle_db_final (void *k, void *data, va_list ap)
+{
+	struct guild_castle *gc = data;
+	if (gc) aFree(gc);
+	return 0;
+}
+void inter_guild_sql_final()
+{
+	if (guild_pt) aFree(guild_pt);
+	if (guild_pt2) aFree(guild_pt2);
+	if (guildcastle_pt) aFree(guildcastle_pt);
+	
+	numdb_final(guild_db_, guild_db_);
+	numdb_final(castle_db_, castle_db_final);
+	numdb_final(guild_expcache_db_, guild_expcache_db_final);
+	numdb_final(guild_infoevent_db_, guild_infoevent_db_final);
+	numdb_final(guild_castleinfoevent_db_, guild_castleinfoevent_db_final);
+
+	return;
+}
 
 // Get guild by its name
 struct guild* search_guildname(char *str)

+ 1 - 0
src/char_sql/int_guild.h

@@ -3,6 +3,7 @@
 
 int inter_guild_parse_frommap(int fd);
 int inter_guild_sql_init();
+void inter_guild_sql_final();
 int inter_guild_mapif_init(int fd);
 
 int inter_guild_leave(int guild_id,int account_id,int char_id);

+ 4 - 0
src/char_sql/int_party.c

@@ -237,6 +237,10 @@ int inter_party_sql_init(){
 
 	return 0;
 }
+void inter_party_sql_final(){
+	if (party_pt) aFree(party_pt);
+	return;
+}
 
 
 // Search for the party according to its name

+ 1 - 0
src/char_sql/int_party.h

@@ -3,6 +3,7 @@
 
 int inter_party_parse_frommap(int fd);
 int inter_party_sql_init();
+void inter_party_sql_final();
 int inter_party_leave(int party_id,int account_id);
 
 #endif

+ 4 - 0
src/char_sql/int_pet.c

@@ -136,6 +136,10 @@ int inter_pet_sql_init(){
 
 	return 0;
 }
+void inter_pet_sql_final(){
+	if (pet_pt) aFree(pet_pt);
+	return;
+}
 //----------------------------------
 int inter_pet_delete(int pet_id){
 	printf("request delete pet: %d.......\n",pet_id);

+ 1 - 0
src/char_sql/int_pet.h

@@ -2,6 +2,7 @@
 #define _INT_PET_H_
 
 int inter_pet_init();
+void inter_pet_sql_final();
 int inter_pet_save();
 int inter_pet_delete(int pet_id);
 

+ 7 - 0
src/char_sql/int_storage.c

@@ -166,6 +166,13 @@ int inter_storage_sql_init(){
 
 	return 1;
 }
+// storage data finalize
+void inter_storage_sql_final()
+{
+	if (storage_pt) aFree(storage_pt);
+	if (guild_storage_pt) aFree(guild_storage_pt);	 
+	return;
+}
 // q?f[^?
 int inter_storage_delete(int account_id)
 {

+ 1 - 0
src/char_sql/int_storage.h

@@ -2,6 +2,7 @@
 #define _INT_STORAGE_H_
 
 int inter_storage_sql_init();
+void inter_storage_sql_final();
 int inter_storage_delete(int account_id);
 int inter_guild_storage_delete(int guild_id);
 

+ 20 - 0
src/char_sql/inter.c

@@ -290,12 +290,32 @@ int inter_init(const char *file)
 	inter_pet_sql_init();
 	inter_accreg_sql_init();
 
+	atexit(inter_final);
+
 	//printf ("interserver timer initializing : %d sec...\n",autosave_interval);
 	//i=add_timer_interval(gettick()+autosave_interval,inter_save_timer,0,0,autosave_interval);
 
 	return 0;
 }
 
+// finalize
+int wis_db_final (void *k, void *data, va_list ap) {
+	struct WisData *p = data;
+	if (p) aFree(p);
+	return 0;
+}
+void inter_final() {
+	numdb_final(wis_db, wis_db_final);
+
+	inter_guild_sql_final();
+	inter_storage_sql_final();
+	inter_party_sql_final();
+	inter_pet_sql_final();
+	
+	if (accreg_pt) aFree(accreg_pt);
+	return;
+}
+
 int inter_mapif_init(int fd) {
 	inter_guild_mapif_init(fd);
 

+ 1 - 1
src/char_sql/inter.h

@@ -2,10 +2,10 @@
 #define _INTER_H_
 
 int inter_init(const char *file);
+void inter_final();
 int inter_parse_frommap(int fd);
 int inter_mapif_init(int fd);
 
-
 int inter_check_length(int fd,int length);
 
 int inter_log(char *fmt,...);

+ 6 - 6
src/common/core.c

@@ -285,6 +285,12 @@ int main(int argc,char **argv)
 {
 	int next;
 
+	display_title();
+#ifdef USE_MEMMGR
+	// call this first so it'll be finalised last
+	do_init_memmgr(argv[0]); // 一番最初に実行する必要がある
+#endif
+
 	sscanf(argv[0], "./%24[^\n]", server_type);	// map/char/login?
 	atexit(log_uptime);
 	pid_create(argv[0]);
@@ -305,12 +311,6 @@ int main(int argc,char **argv)
 		compat_signal(SIGTRAP, SIG_DFL);
 	#endif
 
-	display_title();
-
-#ifdef USE_MEMMGR
-	do_init_memmgr(argv[0]); // 一番最初に実行する必要がある
-#endif
-
 	tick_ = time(0);
 	ticks = gettick();
 

+ 1 - 3
src/common/malloc.c

@@ -7,9 +7,6 @@
 #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 )
@@ -537,6 +534,7 @@ static void memmer_exit(void) {
 		printf("memmgr: no memory leaks found.\n");
 	} else {
 		printf("memmgr: memory leaks found.\n");
+		fclose(fp);
 	}
 }
 

+ 3 - 0
src/common/malloc.h

@@ -3,6 +3,9 @@
 
 #include <stdlib.h>
 
+// 独自メモリマネージャを使用する場合、次のコメントを外してください。
+// #define USE_MEMMGR
+
 #if defined(DMALLOC)
 
 #	include "dmalloc.h"

+ 3 - 5
src/common/socket.c

@@ -943,11 +943,9 @@ void do_final_socket(void)
 		aFree(access_deny);
 
 	// session[0] ‚̃_ƒ~�[ƒf�[ƒ^‚ð�í�œ
-	if (session[0]) {
-		aFree(session[0]->rdata);
-		aFree(session[0]->wdata);
-		aFree(session[0]);
-	}
+	aFree(session[0]->rdata);
+	aFree(session[0]->wdata);
+	aFree(session[0]);	
 }
 
 void do_socket(void)

+ 1 - 3
src/common/timer.h

@@ -36,11 +36,9 @@ int addtick_timer(int tid,unsigned int tick);
 struct TimerData *get_timer(int tid);
 
 int do_timer(unsigned int tick);
+void timer_final();
 
 int add_timer_func_list(int (*)(int,unsigned int,int,int),char*);
-void do_final_timer(void);
 char* search_timer_func_list(int (*)(int,unsigned int,int,int));
 
-extern void timer_final();
-
 #endif	// _TIMER_H_

+ 2 - 1
src/login/login.c

@@ -3923,11 +3923,12 @@ void do_final(void) {
 			memset(&server[i], 0, sizeof(struct mmo_char_server));
 			close(fd);
 			delete_session(fd);
-			if(session[fd]) aFree(session[fd]);
 		}
 	}
 	close(login_fd);
 	delete_session(login_fd);
+	exit_dbn();
+	timer_final();
 
 	login_log("----End of login-server (normal end with closing of all files)." RETCODE);
 

+ 24 - 19
src/login_sql/login.c

@@ -41,30 +41,19 @@ void Gettimeofday(struct timeval *timenow)
 #include <signal.h>
 #include <fcntl.h>
 #include <string.h>
-#include "malloc.h"
 
 //add include for DBMS(mysql)
 #include <mysql.h>
 
-#include "../common/strlib.h"
-#include "timer.h"
-/*
-#include "timer.h"
-#include "core.h"
-#include "socket.h"
-#include "login.h"
-#include "mmo.h"
-#include "version.h"
-#include "db.h"
-*/
-
 #include "../common/core.h"
 #include "../common/socket.h"
-#include "login.h"
-#include "../common/mmo.h"
-#include "../common/version.h"
+#include "../common/malloc.h"
 #include "../common/db.h"
 #include "../common/timer.h"
+#include "../common/strlib.h"
+#include "../common/mmo.h"
+#include "../common/version.h"
+#include "login.h"
 
 #ifdef PASSWORDENC
 #include "md5calc.h"
@@ -1835,6 +1824,24 @@ int flush_timer(int tid, unsigned int tick, int id, int data){
 	return 0;
 }
 
+//--------------------------------------
+// Function called at exit of the server
+//--------------------------------------
+static int online_db_final(void *key,void *data,va_list ap)
+{
+	int *p = data;
+	if (p) aFree(p);
+	return 0;
+}
+void do_final(void) {
+	//sync account when terminating.
+	//but no need when you using DBMS (mysql)
+	mmo_db_close();
+	numdb_final(online_db, online_db_final);
+	exit_dbn();
+	timer_final();
+}
+
 int do_init(int argc,char **argv){
 	//initialize login server
 	int i;
@@ -1876,9 +1883,7 @@ int do_init(int argc,char **argv){
 	printf ("Running mmo_auth_sqldb_init()\n");
 	mmo_auth_sqldb_init();
 	printf ("finished mmo_auth_sqldb_init()\n");
-	//sync account when terminating.
-	//but no need when you using DBMS (mysql)
-	set_termfunc(mmo_db_close);
+	set_termfunc(do_final);
 
 	//set default parser as parse_login function
 	set_defaultparse(parse_login);

+ 48 - 60
src/map/map.c

@@ -1697,24 +1697,24 @@ int map_addnpc(int m,struct npc_data *nd) {
 }
 
 void map_removenpc(void) {
-    int i,m,n=0;
-
-    for(m=0;m<map_num;m++) {
-        for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++) {
-            if(map[m].npc[i]!=NULL) {
-                clif_clearchar_area(&map[m].npc[i]->bl,2);
-                map_delblock(&map[m].npc[i]->bl);
-                numdb_erase(id_db,map[m].npc[i]->bl.id);
-                if(map[m].npc[i]->bl.subtype==SCRIPT) {
-//                    aFree(map[m].npc[i]->u.scr.script);
-//                    aFree(map[m].npc[i]->u.scr.label_list);
-                }
-                aFree(map[m].npc[i]);
-                map[m].npc[i] = NULL;
-                n++;
-            }
-        }
-    }
+	int i,m,n=0;
+
+	for(m=0;m<map_num;m++) {
+		for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++) {
+			if(map[m].npc[i]!=NULL) {
+				clif_clearchar_area(&map[m].npc[i]->bl,2);
+				map_delblock(&map[m].npc[i]->bl);
+				numdb_erase(id_db,map[m].npc[i]->bl.id);
+				if(map[m].npc[i]->bl.subtype==SCRIPT) {
+					aFree(map[m].npc[i]->u.scr.script);
+					aFree(map[m].npc[i]->u.scr.label_list);
+				}
+				aFree(map[m].npc[i]);
+				map[m].npc[i] = NULL;
+				n++;
+			}
+		}
+	}
 
 	sprintf(tmp_output,"Successfully removed and freed from memory '"CL_WHITE"%d"CL_RESET"' NPCs.\n",n);
 	ShowStatus(tmp_output);
@@ -3097,29 +3097,20 @@ int flush_timer(int tid, unsigned int tick, int id, int data){
 	return 0;
 }
 
-int id_db_final(void *k,void *d,va_list ap)
+int id_db_final(void *k,void *d,va_list ap) { return 0; }
+int map_db_final(void *k,void *d,va_list ap) { return 0; }
+int nick_db_final(void *k,void *d,va_list ap)
 {
-	struct mob_data *id;
-	nullpo_retr(0, id = (struct mob_data*)d);
-	if(id->lootitem)
-		aFree(id->lootitem);
-	if(id)
-		aFree(id);
+	char *p = d;
+	if (p) aFree(p);
 	return 0;
 }
-
-int map_db_final(void *k,void *d,va_list ap)
+int charid_db_final(void *k,void *d,va_list ap)
 {
-	struct map_data *id;
-	nullpo_retr(0, id = (struct map_data*)d);
-	if(id->gat)
-		aFree(id->gat);
-	if(id)
-		aFree(id);
+	struct charid2nick *p = d;
+	if (p) aFree(p);
 	return 0;
 }
-int nick_db_final(void *k,void *d,va_list ap){ return 0; }
-int charid_db_final(void *k,void *d,va_list ap){ return 0; }
 int cleanup_sub(struct block_list *bl, va_list ap) {
 	nullpo_retr(0, bl);
 
@@ -3152,12 +3143,12 @@ int cleanup_sub(struct block_list *bl, va_list ap) {
  *------------------------------------------
  */
 void do_final(void) {
-    int map_id, i;
+    int i;
 	ShowStatus("Terminating...\n");
 
-    for (map_id = 0; map_id < map_num;map_id++)
-		if(map[map_id].m)
-			map_foreachinarea(cleanup_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, 0, 0);
+    for (i = 0; i < map_num; i++)
+		if(map[i].m)
+			map_foreachinarea(cleanup_sub, i, 0, 0, map[i].xs, map[i].ys, 0, 0);
 
 #ifndef TXT_ONLY
     chrif_char_reset_offline();
@@ -3165,38 +3156,35 @@ void do_final(void) {
 
     chrif_flush_fifo();
 
-    for (i = 0; i < fd_max; i++)
-        delete_session(i);
-
-#if 0
-    map_removenpc();
-
-//    do_final_timer(); (we used timer_final() instead)
-    timer_final();
-//    numdb_final(id_db, id_db_final);
-    strdb_final(map_db, map_db_final);
-    strdb_final(nick_db, nick_db_final);
-    numdb_final(charid_db, charid_db_final);
-
+//#if 0	// why is this here? >_>
 	do_final_chrif(); // この内部でキャラを全て切断する
+	do_final_npc();
+//	map_removenpc();
 	do_final_script();
 	do_final_itemdb();
 	do_final_storage();
 	do_final_guild();
+	do_final_party();
+	do_final_pc();
 	do_final_pet();
-/*
-	for(i=0;i<map_num;i++){
-		if(map[i].gat) {
-			aFree(map[i].gat);
-			map[i].gat=NULL; //isn't it NULL already o_O?
-		}
+
+	for (i=0; i<map_num; i++) {
+		if(map[i].gat) aFree(map[i].gat);
 		if(map[i].block) aFree(map[i].block);
 		if(map[i].block_mob) aFree(map[i].block_mob);
 		if(map[i].block_count) aFree(map[i].block_count);
 		if(map[i].block_mob_count) aFree(map[i].block_mob_count);
 	}
-*/
-#endif
+
+//    do_final_timer(); (we used timer_final() instead)
+    timer_final();
+    numdb_final(id_db, id_db_final);
+	strdb_final(map_db, map_db_final);
+    strdb_final(nick_db, nick_db_final);
+    numdb_final(charid_db, charid_db_final);
+	exit_dbn();
+
+//#endif
 
 #ifndef TXT_ONLY
     map_sql_close();

+ 64 - 28
src/map/npc.c

@@ -2315,7 +2315,37 @@ static int npc_read_indoors(void)
 
 	return 0;
 }
+static int npc_unload(struct npc_data *nd)
+{
+	struct chat_data *cd;
+
+	nullpo_retr (0, nd);
+	if (nd->chat_id && (cd=(struct chat_data*)map_id2bl(nd->chat_id))){
+		aFree (cd);
+		cd = NULL;
+	}	
+	if (nd->bl.subtype == SCRIPT) {
+		if (nd->u.scr.timer_event)
+			aFree(nd->u.scr.timer_event);
+	 	if (nd->u.scr.src_id==0) {
+			if(nd->u.scr.script) {
+				aFree(nd->u.scr.script);
+				nd->u.scr.script=NULL;
+			}
+			if (nd->u.scr.label_list) {
+				aFree(nd->u.scr.label_list);
+				nd->u.scr.label_list = NULL;
+			}
+		}
+	}
+	clif_clearchar_area(&nd->bl, 2);
+	map_delblock(&nd->bl);
+	map_deliddb(&nd->bl);
+	aFree(nd);
+	nd = NULL;
 
+	return 0;
+}
 static int ev_db_final(void *key,void *data,va_list ap)
 {
 	aFree(data);
@@ -2326,6 +2356,30 @@ static int ev_db_final(void *key,void *data,va_list ap)
 static int npcname_db_final(void *key,void *data,va_list ap)
 {
 	return 0;
+}
+/*==========================================
+ * 
+ *------------------------------------------
+ */
+int npc_reload(void)
+{
+	struct npc_data *nd;
+	struct block_list *bl;
+	int i;	
+
+	if(ev_db) 
+		strdb_final(ev_db,ev_db_final);
+	if(npcname_db)
+		strdb_final(npcname_db,npcname_db_final);
+
+	for (i = START_NPC_NUM; i < npc_id; i++) {
+		if((bl = map_id2bl(i)) && bl->type == BL_NPC && (nd = (struct npc_data *)bl))
+			npc_unload(nd);
+	}
+
+	return 0;
+
+	
 }
 /*==========================================
  * �I—¹
@@ -2337,7 +2391,6 @@ int do_final_npc(void)
 	struct block_list *bl;
 	struct npc_data *nd;
 	struct mob_data *md;
-	struct chat_data *cd;
 	struct pet_data *pd;
 
 	if(ev_db)
@@ -2345,31 +2398,14 @@ int do_final_npc(void)
 	if(npcname_db)
 		strdb_final(npcname_db,npcname_db_final);
 
-	for(i=START_NPC_NUM;i<npc_id;i++){
-		if((bl=map_id2bl(i))){
+	npc_clearsrcfile();
+
+	for (i = START_NPC_NUM; i < npc_id; i++){
+		if((bl = map_id2bl(i))){
 			if(bl->type == BL_NPC && (nd = (struct npc_data *)bl)){
-				if(nd->chat_id && (cd=(struct chat_data*)map_id2bl(nd->chat_id))){
-					aFree(cd);
-					cd = NULL;
-				}
-				if(nd->bl.subtype == SCRIPT){
-					if(nd->u.scr.timer_event)
-						aFree(nd->u.scr.timer_event);
-				 	if(nd->u.scr.src_id==0){
-						if(nd->u.scr.script){
-							aFree(nd->u.scr.script);
-							nd->u.scr.script=NULL;
-						}
-						if(nd->u.scr.label_list){
-							aFree(nd->u.scr.label_list);
-							nd->u.scr.label_list = NULL;
-						}
-					}
-				}
-				aFree(nd);
-				nd = NULL;
-			}else if(bl->type == BL_MOB && (md = (struct mob_data *)bl)){
-				if(md->lootitem){
+				npc_unload(nd);
+			}else if (bl->type == BL_MOB && (md = (struct mob_data *)bl)){
+				if (md->lootitem){
 					aFree(md->lootitem);
 					md->lootitem = NULL;
 				}
@@ -2415,10 +2451,10 @@ int do_init_npc(void)
 	// comparing only the first 24 chars of labels that are 50 chars long isn't that nice
 	// will cause "duplicated" labels where actually no dup is...
 	//ev_db=strdb_init(24); 
-	ev_db=strdb_init(51);
-	npcname_db=strdb_init(24);
+	ev_db = strdb_init(51);
+	npcname_db = strdb_init(24);
 
-        ev_db->release = ev_release;
+	ev_db->release = ev_release;
 
 	memset(&ev_tm_b,-1,sizeof(ev_tm_b));
 

+ 5 - 0
src/map/pc.c

@@ -7234,6 +7234,11 @@ int pc_readdb(void)
  * pc? ŒW�‰Šú‰»
  *------------------------------------------
  */
+void do_final_pc(void) {
+	if (gm_account)
+		aFree(gm_account);
+	return;
+}
 int do_init_pc(void) {
 	pc_readdb();
 

+ 1 - 0
src/map/pc.h

@@ -202,6 +202,7 @@ int pc_delspiritball(struct map_session_data *sd,int,int);
 int pc_eventtimer(int tid,unsigned int tick,int id,int data); // for npc_dequeue 
 
 int do_init_pc(void);
+void do_final_pc(void);
 
 enum {ADDITEM_EXIST,ADDITEM_NEW,ADDITEM_OVERAMOUNT};