summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt10
-rw-r--r--src/common/malloc.c114
-rw-r--r--src/common/malloc.h1
3 files changed, 93 insertions, 32 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index e1872693e..4fa49f97a 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -4,7 +4,15 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2008/02/13
- * Merged memory manager updates from old jA revisions (bugreport:663)
+ * Changes to memory manager: [FlavioJS]
+ - fixed blocks that are fully used not being detected (and not freed) in
+ memmgr_final (unfill_prev is NULL for unused blocks and full blocks)
+ - fixed memmgr_final giving the wrong address to _mfree (for small blocks)
+ - added the pointer address to most error messages (and log)
+ - made it append to the log file instead of rewriting it
+ - implemented a function to verify if a memory location is active
+ - other minor changes
+ * Merged memory manager updates from old jA revisions (bugreport:663) [ultramage]
- less overhead and better overflow detection (caution, experimental!)
* Added some security checks in mail system [Zephyrus]
- This supose to fix a bug reported in 622 to limit to MAX_ZENY.
diff --git a/src/common/malloc.c b/src/common/malloc.c
index 88d43b21e..90efd04ee 100644
--- a/src/common/malloc.c
+++ b/src/common/malloc.c
@@ -376,7 +376,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
*(long*)((char*)head_large + sizeof(struct unit_head_large) - sizeof(long) + head_large->size)
!= 0xdeadbeaf)
{
- ShowError("Memory manager: args of aFree is overflowed pointer %s line %d\n", file, line);
+ ShowError("Memory manager: args of aFree 0x%p is overflowed pointer %s line %d\n", ptr, file, line);
} else {
head->size = -1;
if(head_large->prev) {
@@ -398,11 +398,11 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
/* ユニット解放 */
struct block *block = head->block;
if( (char*)head - (char*)block > sizeof(struct block) ) {
- ShowError("Memory manager: args of aFree is invalid pointer %s line %d\n",file,line);
+ 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 is freed pointer %s:%d@%s\n", file, line, func);
+ 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 is overflowed pointer %s line %d\n", file, line);
+ 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;
@@ -443,7 +443,7 @@ static struct block* block_malloc(unsigned short hash)
hash_unfill[0] = hash_unfill[0]->unfill_next;
} else {
/* ブロック用の領域を新たに確保する */
- p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), file,line,func );
+ 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);
@@ -464,6 +464,7 @@ static struct block* block_malloc(unsigned short hash)
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];
@@ -517,20 +518,69 @@ static FILE *log_fp;
static void memmgr_log (char *buf)
{
- time_t raw;
- struct tm* t;
if( !log_fp )
{
- log_fp = fopen(memmer_logfile,"w");
+ time_t raw;
+ struct tm* t;
+
+ log_fp = fopen(memmer_logfile,"at");
if (!log_fp) log_fp = stdout;
- fprintf(log_fp, "Memory manager: Memory leaks found (Revision %s).\n", get_svn_revision());
+
+ 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());
}
- time(&raw);
- t = localtime(&raw);
- fprintf(log_fp, "%04d%02d%02d%02d%02d%02d %s", (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, buf);
+ fprintf(log_fp, "%s", buf);
return;
}
-#endif
+#endif /* LOG_MEMMGR */
+
+/// Returns true if the memory location is active.
+/// Active means it is allocated and points to a usable part.
+///
+/// @param ptr Pointer to the memory
+/// @return true if the memory is active
+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;
+}
static void memmgr_final (void)
{
@@ -539,23 +589,24 @@ static void memmgr_final (void)
#ifdef LOG_MEMMGR
int count = 0;
-#endif
-
+#endif /* LOG_MEMMGR */
+
while (block) {
- if (block->unfill_prev) {
+ 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[128];
+ char buf[1024];
sprintf (buf,
- "%04d : %s line %d size %lu\n", ++count,
- head->file, head->line, (unsigned long)head->size);
+ "%04d : %s line %d size %lu address 0x%p\n", ++count,
+ head->file, head->line, (unsigned long)head->size, ptr);
memmgr_log (buf);
-#endif
+#endif /* LOG_MEMMGR */
// get block pointer and free it [celest]
- _mfree ((char *)head + sizeof(struct unit_head) - sizeof(short), ALC_MARK);
+ _mfree(ptr, ALC_MARK);
}
}
}
@@ -565,12 +616,12 @@ static void memmgr_final (void)
while(large) {
struct unit_head_large *large2;
#ifdef LOG_MEMMGR
- char buf[128];
+ char buf[1024];
sprintf (buf,
- "%04d : %s line %d size %lu\n", ++count,
- large->unit_head.file, large->unit_head.line, (unsigned long)large->unit_head.size);
+ "%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
+#endif /* LOG_MEMMGR */
large2 = large->next;
FREE(large,file,line,func);
large = large2;
@@ -582,7 +633,7 @@ static void memmgr_final (void)
ShowWarning("Memory manager: Memory leaks found and fixed.\n");
fclose(log_fp);
}
-#endif
+#endif /* LOG_MEMMGR */
return;
}
@@ -591,10 +642,11 @@ 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);
-#endif
+ memset(hash_unfill, 0, sizeof(hash_unfill));
+#endif /* LOG_MEMMGR */
return;
}
-#endif
+#endif /* USE_MEMMGR */
/*======================================
@@ -605,10 +657,10 @@ static void memmgr_init (void)
bool malloc_verify(void* ptr)
{
#ifdef USE_MEMMGR
-
-#endif
-
+ return memmgr_verify(ptr);
+#else
return true;
+#endif
}
unsigned int malloc_usage (void)
diff --git a/src/common/malloc.h b/src/common/malloc.h
index 1efc4686f..609f0a700 100644
--- a/src/common/malloc.h
+++ b/src/common/malloc.h
@@ -155,6 +155,7 @@
////////////////////////////////////////////////
+bool malloc_verify(void* ptr);
unsigned int malloc_usage (void);
void malloc_init (void);
void malloc_final (void);