
- Cleaned up the scriptable npc-shop code, it should be crash-proof now. git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@8525 54d463be-8e91-2dee-dedb-b68131a5f0ec
766 lines
21 KiB
C
766 lines
21 KiB
C
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||
// For more information, see LICENCE in the main folder
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include "../common/malloc.h"
|
||
#include "../common/core.h"
|
||
#include "../common/showmsg.h"
|
||
|
||
#ifdef MINICORE
|
||
#undef LOG_MEMMGR
|
||
#endif
|
||
|
||
void* aMalloc_ (size_t size, const char *file, int line, const char *func)
|
||
{
|
||
#ifndef MEMWATCH
|
||
void *ret = MALLOC(size);
|
||
#else
|
||
void *ret = mwMalloc(size, file, line);
|
||
#endif
|
||
// ShowMessage("%s:%d: in func %s: malloc %d\n",file,line,func,size);
|
||
if (ret == NULL){
|
||
ShowFatalError("%s:%d: in func %s: malloc error out of memory!\n",file,line,func);
|
||
exit(1);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
void* aMallocA_ (size_t size, const char *file, int line, const char *func)
|
||
{
|
||
#ifndef MEMWATCH
|
||
void *ret = MALLOCA(size);
|
||
#else
|
||
void *ret = mwMalloc(size, file, line);
|
||
#endif
|
||
// ShowMessage("%s:%d: in func %s: malloc %d\n",file,line,func,size);
|
||
if (ret == NULL){
|
||
ShowFatalError("%s:%d: in func %s: malloc error out of memory!\n",file,line,func);
|
||
exit(1);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
void* aCalloc_ (size_t num, size_t size, const char *file, int line, const char *func)
|
||
{
|
||
#ifndef MEMWATCH
|
||
void *ret = CALLOC(num, size);
|
||
#else
|
||
void *ret = mwCalloc(num, size, file, line);
|
||
#endif
|
||
// ShowMessage("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size);
|
||
if (ret == NULL){
|
||
ShowFatalError("%s:%d: in func %s: calloc error out of memory!\n", file, line, func);
|
||
exit(1);
|
||
}
|
||
return ret;
|
||
}
|
||
void* aCallocA_ (size_t num, size_t size, const char *file, int line, const char *func)
|
||
{
|
||
#ifndef MEMWATCH
|
||
void *ret = CALLOCA(num, size);
|
||
#else
|
||
void *ret = mwCalloc(num, size, file, line);
|
||
#endif
|
||
// ShowMessage("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size);
|
||
if (ret == NULL){
|
||
ShowFatalError("%s:%d: in func %s: calloc error out of memory!\n",file,line,func);
|
||
exit(1);
|
||
}
|
||
return ret;
|
||
}
|
||
void* aRealloc_ (void *p, size_t size, const char *file, int line, const char *func)
|
||
{
|
||
#ifndef MEMWATCH
|
||
void *ret = REALLOC(p, size);
|
||
#else
|
||
void *ret = mwRealloc(p, size, file, line);
|
||
#endif
|
||
// ShowMessage("%s:%d: in func %s: realloc %p %d\n",file,line,func,p,size);
|
||
if (ret == NULL){
|
||
ShowFatalError("%s:%d: in func %s: realloc error out of memory!\n",file,line,func);
|
||
exit(1);
|
||
}
|
||
return ret;
|
||
}
|
||
char* aStrdup_ (const char *p, const char *file, int line, const char *func)
|
||
{
|
||
#ifndef MEMWATCH
|
||
char *ret = STRDUP(p);
|
||
#else
|
||
char *ret = mwStrdup(p, file, line);
|
||
#endif
|
||
// ShowMessage("%s:%d: in func %s: strdup %p\n",file,line,func,p);
|
||
if (ret == NULL){
|
||
ShowFatalError("%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)
|
||
{
|
||
// ShowMessage("%s:%d: in func %s: free %p\n",file,line,func,p);
|
||
if (p)
|
||
#ifndef MEMWATCH
|
||
FREE(p);
|
||
#else
|
||
mwFree(p, file, line);
|
||
#endif
|
||
|
||
p = NULL;
|
||
}
|
||
|
||
#ifdef GCOLLECT
|
||
|
||
void* _bcallocA(size_t size, size_t cnt)
|
||
{
|
||
void *ret = MALLOCA(size * cnt);
|
||
if (ret) //malloc_set(ret, 0, size * cnt);
|
||
malloc_set(ret, 0, size*cnt);
|
||
return ret;
|
||
}
|
||
void* _bcalloc(size_t size, size_t cnt)
|
||
{
|
||
void *ret = MALLOC(size * cnt);
|
||
if (ret) //malloc_set(ret, 0, size * cnt);
|
||
malloc_set(ret, 0, size*cnt);
|
||
return ret;
|
||
}
|
||
char* _bstrdup(const char *chr)
|
||
{
|
||
int len = strlen(chr);
|
||
char *ret = (char*)MALLOC(len + 1);
|
||
if (ret) memcpy(ret, chr, len + 1);
|
||
return ret;
|
||
}
|
||
|
||
#endif
|
||
|
||
#ifdef USE_MEMMGR
|
||
|
||
/* USE_MEMMGR */
|
||
|
||
/*
|
||
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>}<7D>l<EFBFBD>[<5B>W<EFBFBD><57>
|
||
* malloc , free <20>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>I<EFBFBD>ɏo<C98F><6F><EFBFBD><EFBFBD><EFBFBD>悤<EFBFBD>ɂ<EFBFBD><C982><EFBFBD><EFBFBD><EFBFBD><EFBFBD>́B
|
||
* <20><><EFBFBD>G<EFBFBD>ȏ<EFBFBD><C88F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>s<EFBFBD><73><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>̂ŁA<C581><EFBFBD>d<EFBFBD><64><EFBFBD>Ȃ邩<C882><E982A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD><EFBFBD>B
|
||
*
|
||
* <20>f<EFBFBD>[<5B>^<5E>\<5C><><EFBFBD>Ȃǁi<C781><69><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ł<EFBFBD><C582><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>^^; <20>j
|
||
* <20>E<EFBFBD><45><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F095A190>́u<CC81>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>v<EFBFBD>ɕ<EFBFBD><C995><EFBFBD><EFBFBD>āA<C481><41><EFBFBD><EFBFBD><EFBFBD>Ƀu<C983><75><EFBFBD>b<EFBFBD>N<EFBFBD><EFBFBD><F095A190>́u<CC81><75><EFBFBD>j<EFBFBD>b<EFBFBD>g<EFBFBD>v
|
||
* <20>ɕ<EFBFBD><C995><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD><DC82>B<EFBFBD><42><EFBFBD>j<EFBFBD>b<EFBFBD>g<EFBFBD>̃T<CC83>C<EFBFBD>Y<EFBFBD>́A<CD81>P<EFBFBD>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>̗e<CC97>ʂ<CA82><F095A190>ɋϓ<C98B><CF93>z<EFBFBD><7A>
|
||
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̂ł<CC82><C582>B<EFBFBD><42><EFBFBD>Ƃ<EFBFBD><C682>A<CE81>P<EFBFBD><50><EFBFBD>j<EFBFBD>b<EFBFBD>g32KB<4B>̏ꍇ<CC8F>A<EFBFBD>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>P<EFBFBD><EFBFBD>32Byte<74>̃<EFBFBD>
|
||
* <20>j<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD>A1024<32>W<C28F>܂<EFBFBD><DC82>ďo<C48F><6F><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD><EFBFBD><EFBFBD>A64Byte<74>̃<EFBFBD><CC83>j<EFBFBD>b<EFBFBD>g<EFBFBD><67> 512<31>W<C28F>܂<EFBFBD><DC82><EFBFBD>
|
||
* <20>o<EFBFBD><6F><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>肵<EFBFBD>܂<EFBFBD><DC82>B<EFBFBD>ipadding,unit_head <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>j
|
||
*
|
||
* <20>E<EFBFBD>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD><4E><EFBFBD>m<EFBFBD>̓<EFBFBD><CD83><EFBFBD><EFBFBD>N<EFBFBD><4E><EFBFBD>X<EFBFBD>g(block_prev,block_next) <20>łȂ<C282><C882><EFBFBD><EFBFBD>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C
|
||
* <20>Y<EFBFBD><59><EFBFBD><EFBFBD><EFBFBD>u<C283><75><EFBFBD>b<EFBFBD>N<EFBFBD><4E><EFBFBD>m<EFBFBD><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>N<EFBFBD><4E><EFBFBD>X<EFBFBD>g(samesize_prev,samesize_nect) <20>ł<C582>
|
||
* <20><><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>܂<EFBFBD><DC82>B<EFBFBD><42><EFBFBD><EFBFBD><EFBFBD>ɂ<EFBFBD><C982><EFBFBD><EFBFBD>A<EFBFBD>s<EFBFBD>v<EFBFBD>ƂȂ<C682><C882><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̍ė<CC8D><C497>p<EFBFBD><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>I<EFBFBD>ɍs<C98D><73><EFBFBD>܂<EFBFBD><DC82>B
|
||
*/
|
||
|
||
/* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>ɓ<EFBFBD><C993><EFBFBD><EFBFBD>f<EFBFBD>[<5B>^<5E><> */
|
||
#define BLOCK_DATA_SIZE 80*1024
|
||
|
||
/* <20><><EFBFBD>x<EFBFBD>Ɋm<C98A>ۂ<EFBFBD><DB82><EFBFBD><EFBFBD>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>̐<EFBFBD><CC90>B */
|
||
#define BLOCK_ALLOC 32
|
||
|
||
/* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>̃A<CC83><41><EFBFBD>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>g */
|
||
#define BLOCK_ALIGNMENT 64
|
||
|
||
/* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N */
|
||
struct block {
|
||
int block_no; /* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>ԍ<EFBFBD> */
|
||
struct block* block_prev; /* <20>O<EFBFBD>Ɋm<C98A>ۂ<EFBFBD><DB82><EFBFBD><EFBFBD>̈<EFBFBD> */
|
||
struct block* block_next; /* <20><><EFBFBD>Ɋm<C98A>ۂ<EFBFBD><DB82><EFBFBD><EFBFBD>̈<EFBFBD> */
|
||
int samesize_no; /* <20><><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y<EFBFBD>̔ԍ<CC94> */
|
||
struct block* samesize_prev; /* <20><><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y<EFBFBD>̑O<CC91>̗̈<CC97> */
|
||
struct block* samesize_next; /* <20><><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y<EFBFBD>̎<EFBFBD><CC8E>̗̈<CC97> */
|
||
size_t unit_size; /* <20><><EFBFBD>j<EFBFBD>b<EFBFBD>g<EFBFBD>̃o<CC83>C<EFBFBD>g<EFBFBD><67> 0=<3D><><EFBFBD>g<EFBFBD>p */
|
||
size_t unit_hash; /* <20><><EFBFBD>j<EFBFBD>b<EFBFBD>g<EFBFBD>̃n<CC83>b<EFBFBD>V<EFBFBD><56> */
|
||
int unit_count; /* <20><><EFBFBD>j<EFBFBD>b<EFBFBD>g<EFBFBD>̐<EFBFBD> */
|
||
int unit_used; /* <20>g<EFBFBD>p<EFBFBD>ς݃<CF82><DD83>j<EFBFBD>b<EFBFBD>g */
|
||
char data[BLOCK_DATA_SIZE];
|
||
};
|
||
|
||
struct unit_head {
|
||
struct block* block;
|
||
size_t size;
|
||
const char* file;
|
||
int line;
|
||
unsigned int checksum;
|
||
};
|
||
|
||
struct chunk {
|
||
char *block;
|
||
struct chunk *next;
|
||
};
|
||
|
||
static struct block* block_first = NULL;
|
||
static struct block* block_last = NULL;
|
||
static struct block* block_unused = NULL;
|
||
|
||
/* <20><><EFBFBD>j<EFBFBD>b<EFBFBD>g<EFBFBD>ւ̃n<CC83>b<EFBFBD>V<EFBFBD><56><EFBFBD>B80KB/64Byte = 1280<38><30> */
|
||
static struct block* unit_first[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* <20>ŏ<EFBFBD> */
|
||
static struct block* unit_unfill[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* <20><><EFBFBD>܂<EFBFBD><DC82>ĂȂ<C482> */
|
||
static struct block* unit_last[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* <20>Ō<EFBFBD> */
|
||
|
||
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><67><EFBFBD>Ȃ<F182B982><C882>̈<EFBFBD><CC88>p<EFBFBD>̃f<CC83>[<5B>^ */
|
||
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 chunk *chunk_first = NULL;
|
||
|
||
static struct block* block_malloc(void);
|
||
static void block_free(struct block* p);
|
||
static void memmgr_info(void);
|
||
static unsigned int memmgr_usage_bytes = 0;
|
||
|
||
void* _mmalloc(size_t size, const char *file, int line, const char *func ) {
|
||
int i;
|
||
struct block *block;
|
||
size_t size_hash;
|
||
|
||
if (((long) size) < 0) {
|
||
printf("_mmalloc: %d\n", size);
|
||
return 0;
|
||
}
|
||
|
||
size_hash = (size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT;
|
||
if(size == 0) {
|
||
return NULL;
|
||
}
|
||
memmgr_usage_bytes += size;
|
||
|
||
/* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD><4E><EFBFBD><EFBFBD><F092B482><EFBFBD><EFBFBD>̈<EFBFBD><CC88>̊m<CC8A>ۂɂ́Amalloc() <20><><EFBFBD>p<EFBFBD><70><EFBFBD><EFBFBD> */
|
||
/* <20><><EFBFBD>̍ہAunit_head.block <20><> NULL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ċ<EFBFBD><C48B>ʂ<EFBFBD><CA82><EFBFBD> */
|
||
if(size_hash * BLOCK_ALIGNMENT > 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;
|
||
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;
|
||
*(int*)((char*)p + sizeof(struct unit_head_large) - sizeof(int) + size) = 0xdeadbeaf;
|
||
return (char *)p + sizeof(struct unit_head_large) - sizeof(int);
|
||
} else {
|
||
ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line);
|
||
exit(1);
|
||
}
|
||
}
|
||
|
||
/* <20><><EFBFBD><EFBFBD><EFBFBD>T<EFBFBD>C<EFBFBD>Y<EFBFBD>̃u<CC83><75><EFBFBD>b<EFBFBD>N<EFBFBD><4E><EFBFBD>m<EFBFBD>ۂ<EFBFBD><DB82><EFBFBD><EFBFBD>Ă<EFBFBD><C482>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD>A<EFBFBD>V<EFBFBD><56><EFBFBD>Ɋm<C98A>ۂ<EFBFBD><DB82><EFBFBD> */
|
||
if(unit_unfill[size_hash] == NULL) {
|
||
block = block_malloc();
|
||
if(unit_first[size_hash] == NULL) {
|
||
/* <20><><EFBFBD><EFBFBD><EFBFBD>m<EFBFBD><6D> */
|
||
unit_first[size_hash] = block;
|
||
unit_last[size_hash] = block;
|
||
block->samesize_no = 0;
|
||
block->samesize_prev = NULL;
|
||
block->samesize_next = NULL;
|
||
} else {
|
||
/* <20>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
||
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_hash * BLOCK_ALIGNMENT + sizeof(struct unit_head);
|
||
block->unit_count = (int)(BLOCK_DATA_SIZE / block->unit_size);
|
||
block->unit_used = 0;
|
||
block->unit_hash = size_hash;
|
||
/* <20><><EFBFBD>g<EFBFBD>pFlag<61>𗧂Ă<F097A782> */
|
||
for(i=0;i<block->unit_count;i++) {
|
||
((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL;
|
||
}
|
||
}
|
||
/* <20><><EFBFBD>j<EFBFBD>b<EFBFBD>g<EFBFBD>g<EFBFBD>p<EFBFBD><EFBFBD><C290><EFBFBD><EFBFBD>Z */
|
||
block = unit_unfill[size_hash];
|
||
block->unit_used++;
|
||
|
||
/* <20><><EFBFBD>j<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD>S<EFBFBD>Ďg<C48E><67><EFBFBD>ʂ<EFBFBD><CA82><EFBFBD><EFBFBD><EFBFBD> */
|
||
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
|
||
);
|
||
}
|
||
|
||
/* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>̒<EFBFBD><CC92>̋<CC8B><F382AB83>j<EFBFBD>b<EFBFBD>g<EFBFBD>{<7B><> */
|
||
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;
|
||
*(int*)((char*)head + sizeof(struct unit_head) - sizeof(int) + size) = 0xdeadbeaf;
|
||
return (char *)head + sizeof(struct unit_head) - sizeof(int);
|
||
}
|
||
}
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD>ɗ<EFBFBD><C997>Ă͂<C482><CD82><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882>B
|
||
ShowFatalError("Memory manager::memmgr_malloc() serious error (allocating %d+%d bytes at %s:%d)\n", sizeof(struct unit_head_large), size, file, line);
|
||
memmgr_info();
|
||
exit(1);
|
||
return NULL;
|
||
};
|
||
|
||
void* _mcalloc(size_t num, size_t size, const char *file, int line, const char *func ) {
|
||
void *p = _mmalloc(num * size,file,line,func);
|
||
//malloc_set(p,0,num * size);
|
||
malloc_set(p,0,num*size);
|
||
return p;
|
||
}
|
||
|
||
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(int)))->size;
|
||
if(old_size > size) {
|
||
// <20>T<EFBFBD>C<EFBFBD>Y<EFBFBD>k<EFBFBD><6B> -> <20><><EFBFBD>̂܂ܕԂ<DC95><D482>i<EFBFBD>蔲<EFBFBD><E894B2><EFBFBD>j
|
||
return memblock;
|
||
} else {
|
||
// <20>T<EFBFBD>C<EFBFBD>Y<EFBFBD>g<EFBFBD><67>
|
||
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 ) {
|
||
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 ) {
|
||
struct unit_head *head;
|
||
size_t size_hash;
|
||
|
||
if (ptr == NULL)
|
||
return;
|
||
|
||
head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(int));
|
||
size_hash = (head->size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT;
|
||
|
||
if(head->block == NULL) {
|
||
if(size_hash * BLOCK_ALIGNMENT > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
|
||
/* malloc() <20>Œ<EFBFBD><C592>Ɋm<C98A>ۂ<EFBFBD><DB82>ꂽ<EFBFBD>̈<EFBFBD> */
|
||
struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(int));
|
||
if(
|
||
*(int*)((char*)head_large + sizeof(struct unit_head_large) - sizeof(int) + head->size)
|
||
!= 0xdeadbeaf)
|
||
{
|
||
ShowError("Memory manager: args of aFree is overflowed pointer %s line %d\n", file, line);
|
||
}
|
||
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;
|
||
}
|
||
head->block = NULL;
|
||
memmgr_usage_bytes -= head->size;
|
||
FREE (head_large);
|
||
} else {
|
||
ShowError("Memory manager: args of aFree is freed pointer %s:%d@%s\n", file, line, func);
|
||
}
|
||
ptr = NULL;
|
||
return;
|
||
} else {
|
||
/* <20><><EFBFBD>j<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD> */
|
||
struct block *block = head->block;
|
||
if((unsigned long)block % sizeof(struct block) != 0) {
|
||
ShowError("Memory manager: args of aFree is not valid pointer %s line %d\n", file, line);
|
||
} else if(*(int*)((char*)head + sizeof(struct unit_head) - sizeof(int) + head->size) != 0xdeadbeaf) {
|
||
ShowError("Memory manager: args of aFree is overflowed pointer %s line %d\n", file, line);
|
||
} else {
|
||
head->block = NULL;
|
||
memmgr_usage_bytes -= head->size;
|
||
if(--block->unit_used == 0) {
|
||
/* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>̉<EFBFBD><CC89><EFBFBD> */
|
||
if(unit_unfill[block->unit_hash] == block) {
|
||
/* <20><EFBFBD><F382AB83>j<EFBFBD>b<EFBFBD>g<EFBFBD>Ɏw<C98E>肳<EFBFBD><E882B3><EFBFBD>Ă<EFBFBD><C482><EFBFBD> */
|
||
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) {
|
||
/* <20>Ɨ<EFBFBD><C697>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>̉<EFBFBD><CC89><EFBFBD> */
|
||
unit_first[block->unit_hash] = NULL;
|
||
unit_last[block->unit_hash] = NULL;
|
||
unit_unfill[block->unit_hash] = NULL;
|
||
} else if(block->samesize_prev == NULL) {
|
||
/* <20>擪<EFBFBD>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>̉<EFBFBD><CC89><EFBFBD> */
|
||
unit_first[block->unit_hash] = block->samesize_next;
|
||
(block->samesize_next)->samesize_prev = NULL;
|
||
} else if(block->samesize_next == NULL) {
|
||
/* <20><><EFBFBD>[<5B>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>̉<EFBFBD><CC89><EFBFBD> */
|
||
unit_last[block->unit_hash] = block->samesize_prev;
|
||
(block->samesize_prev)->samesize_next = NULL;
|
||
} else {
|
||
/* <20><><EFBFBD>ԃu<D483><75><EFBFBD>b<EFBFBD>N<EFBFBD>̉<EFBFBD><CC89><EFBFBD> */
|
||
(block->samesize_next)->samesize_prev = block->samesize_prev;
|
||
(block->samesize_prev)->samesize_next = block->samesize_next;
|
||
}
|
||
block_free(block);
|
||
} else {
|
||
/* <20><EFBFBD><F382AB83>j<EFBFBD>b<EFBFBD>g<EFBFBD>̍Đݒ<C490> */
|
||
if(
|
||
unit_unfill[block->unit_hash] == NULL ||
|
||
unit_unfill[block->unit_hash]->samesize_no > block->samesize_no
|
||
) {
|
||
unit_unfill[block->unit_hash] = block;
|
||
}
|
||
}
|
||
ptr = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* <20><><EFBFBD>݂̏<CC8F><F38BB582>\<5C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
||
static void memmgr_info(void) {
|
||
int i;
|
||
struct block *p;
|
||
ShowInfo("** Memory Manager Information **\n");
|
||
if(block_first == NULL) {
|
||
ShowMessage("Uninitialized.\n");
|
||
return;
|
||
}
|
||
ShowMessage(
|
||
"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++) {
|
||
ShowMessage(" Block #%04u : ",p->block_no);
|
||
if(p->unit_size == 0) {
|
||
ShowMessage("unused.\n");
|
||
} else {
|
||
ShowMessage(
|
||
"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) {
|
||
ShowMessage("NULL");
|
||
} else {
|
||
ShowMessage("%04u",(p->samesize_prev)->block_no);
|
||
}
|
||
ShowMessage(" next:");
|
||
if(p->samesize_next == NULL) {
|
||
ShowMessage("NULL");
|
||
} else {
|
||
ShowMessage("%04u",(p->samesize_next)->block_no);
|
||
}
|
||
ShowMessage("\n");
|
||
}
|
||
p = p->block_next;
|
||
}
|
||
}
|
||
|
||
/* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD><4E><EFBFBD>m<EFBFBD>ۂ<EFBFBD><DB82><EFBFBD> */
|
||
static struct block* block_malloc(void) {
|
||
if(block_unused != NULL) {
|
||
/* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>p<EFBFBD>̗̈<CC97><CC88>͊m<CD8A>ۍς<DB8D> */
|
||
struct block* ret = block_unused;
|
||
do {
|
||
block_unused = block_unused->block_next;
|
||
} while(block_unused != NULL && block_unused->unit_size != 0);
|
||
return ret;
|
||
} else {
|
||
/* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>p<EFBFBD>̗̈<CC97><CC88><EFBFBD><EFBFBD>V<EFBFBD><56><EFBFBD>Ɋm<C98A>ۂ<EFBFBD><DB82><EFBFBD> */
|
||
int i;
|
||
int block_no;
|
||
struct block* p;
|
||
struct chunk* chunk;
|
||
char *pb = (char *) CALLOC (sizeof(struct block),BLOCK_ALLOC + 1);
|
||
if(pb == NULL) {
|
||
ShowFatalError("Memory manager::block_alloc failed.\n");
|
||
exit(1);
|
||
}
|
||
|
||
// store original block address in chunk
|
||
chunk = (struct chunk *) MALLOC (sizeof(struct chunk));
|
||
if (chunk == NULL) {
|
||
ShowFatalError("Memory manager::block_alloc failed.\n");
|
||
exit(1);
|
||
}
|
||
chunk->block = pb;
|
||
chunk->next = (chunk_first) ? chunk_first : NULL;
|
||
chunk_first = chunk;
|
||
|
||
// <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>̃|<7C>C<EFBFBD><43><EFBFBD>^<5E>̐擪<CC90><E693AA>sizeof(block) <20>A<EFBFBD><41><EFBFBD>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD>ɑ<EFBFBD><C991><EFBFBD><EFBFBD><EFBFBD>
|
||
// <20><><EFBFBD>̃A<CC83>h<EFBFBD><68><EFBFBD>X<EFBFBD><58>free() <20><><EFBFBD>邱<EFBFBD>Ƃ͂Ȃ<CD82><C882>̂ŁA<C581><41><EFBFBD>ڃ|<7C>C<EFBFBD><43><EFBFBD>^<5E><><EFBFBD>ύX<CF8D><58><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>B
|
||
pb += sizeof(struct block) - ((unsigned long)pb % sizeof(struct block));
|
||
p = (struct block*)pb;
|
||
if(block_first == NULL) {
|
||
/* <20><><EFBFBD><EFBFBD><EFBFBD>m<EFBFBD><6D> */
|
||
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];
|
||
/* <20>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD><4E><EFBFBD>A<EFBFBD><41><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
||
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;
|
||
}
|
||
|
||
/* <20><><EFBFBD>g<EFBFBD>p<EFBFBD>u<EFBFBD><75><EFBFBD>b<EFBFBD>N<EFBFBD>ւ̃|<7C>C<EFBFBD><43><EFBFBD>^<5E><><EFBFBD>X<EFBFBD>V */
|
||
block_unused = &p[1];
|
||
p->unit_size = 1;
|
||
return p;
|
||
}
|
||
}
|
||
|
||
static void block_free(struct block* p) {
|
||
/* free() <20><><EFBFBD><EFBFBD><EFBFBD>ɁA<C981><41><EFBFBD>g<EFBFBD>p<EFBFBD>t<EFBFBD><74><EFBFBD>O<EFBFBD><4F><EFBFBD>t<EFBFBD><74><EFBFBD>邾<EFBFBD><E982BE> */
|
||
p->unit_size = 0;
|
||
/* <20><><EFBFBD>g<EFBFBD>p<EFBFBD>|<7C>C<EFBFBD><43><EFBFBD>^<5E>[<5B><><EFBFBD>X<EFBFBD>V<EFBFBD><56><EFBFBD><EFBFBD> */
|
||
if(block_unused == NULL) {
|
||
block_unused = p;
|
||
} else if(block_unused->block_no > p->block_no) {
|
||
block_unused = p;
|
||
}
|
||
}
|
||
|
||
unsigned int memmgr_usage (void)
|
||
{
|
||
return memmgr_usage_bytes / 1024;
|
||
}
|
||
|
||
#ifdef LOG_MEMMGR
|
||
static char memmer_logfile[128];
|
||
static FILE *log_fp;
|
||
|
||
static void memmgr_log (char *buf)
|
||
{
|
||
if (!log_fp) {
|
||
log_fp = fopen(memmer_logfile,"w");
|
||
if (!log_fp) log_fp = stdout;
|
||
fprintf(log_fp, "Memory manager: Memory leaks found (Revision %s).\n", get_svn_revision());
|
||
}
|
||
fprintf(log_fp, buf);
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
static void memmgr_final (void)
|
||
{
|
||
struct block *block = block_first;
|
||
struct chunk *chunk = chunk_first, *chunk2;
|
||
struct unit_head_large *large = unit_head_large_first, *large2;
|
||
int i;
|
||
|
||
#ifdef LOG_MEMMGR
|
||
int count = 0;
|
||
char buf[128];
|
||
#endif
|
||
|
||
while (block) {
|
||
if (block->unit_size) {
|
||
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)
|
||
{
|
||
#ifdef LOG_MEMMGR
|
||
sprintf (buf,
|
||
"%04d : %s line %d size %d\n", ++count,
|
||
head->file, head->line, head->size);
|
||
memmgr_log (buf);
|
||
#endif
|
||
// get block pointer and free it [celest]
|
||
_mfree ((char *)head + sizeof(struct unit_head) - sizeof(int), ALC_MARK);
|
||
}
|
||
}
|
||
}
|
||
//if (block->block_no >= block2->block_no + BLOCK_ALLOC - 1) {
|
||
// reached a new block array
|
||
//block = block->block_next;
|
||
|
||
/* Okay wise guys... this is how block2 was allocated: [Skotlex]
|
||
struct block* p;
|
||
char *pb = (char *) CALLOC (sizeof(struct block),BLOCK_ALLOC + 1);
|
||
pb += sizeof(struct block) - ((unsigned long)pb % sizeof(struct block));
|
||
p = (struct block*)pb;
|
||
|
||
The reason we get an invalid pointer is that we allocated pb, not p.
|
||
So how do you get pb when you only have p?
|
||
The answer is, you can't, because the original pointer was lost when
|
||
memory-aligning the block. So we either forget this FREE or use a
|
||
self-reference...
|
||
Since we are already quitting, it might be ok to just not free the block
|
||
as it is.
|
||
*/
|
||
// didn't realise that before o.o -- block chunks are now freed below [celest]
|
||
// FREE(block2);
|
||
//block2 = block;
|
||
//continue;
|
||
//}
|
||
block = block->block_next;
|
||
}
|
||
|
||
// free the allocated block chunks
|
||
chunk = chunk_first;
|
||
while (chunk) {
|
||
chunk2 = chunk->next;
|
||
FREE(chunk->block);
|
||
FREE(chunk);
|
||
chunk = chunk2;
|
||
}
|
||
|
||
while(large) {
|
||
large2 = large->next;
|
||
#ifdef LOG_MEMMGR
|
||
sprintf (buf,
|
||
"%04d : %s line %d size %d\n", ++count,
|
||
large->unit_head.file, large->unit_head.line, large->unit_head.size);
|
||
memmgr_log (buf);
|
||
#endif
|
||
FREE (large);
|
||
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);
|
||
}
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
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
|
||
return;
|
||
}
|
||
#endif
|
||
|
||
#if defined(MEMSET_TURBO) && defined(_WIN32)
|
||
void malloc_set(void *dest, int value, int count){
|
||
_asm
|
||
{
|
||
mov eax, value
|
||
mov ecx, count
|
||
mov ebx, ecx
|
||
mov edi, dest
|
||
shr ecx, 2
|
||
test ecx, ecx
|
||
jz ByteOp
|
||
shl ecx, 2
|
||
sub ebx, ecx
|
||
shr ecx, 2
|
||
rep stosd
|
||
test ebx, ebx
|
||
jz Done
|
||
ByteOp:
|
||
mov ecx, ebx
|
||
rep stosb
|
||
Done:
|
||
}
|
||
}
|
||
// Sets 32-bit aligned memory.
|
||
void malloc_tsetdword(void *dest, int value, int count){
|
||
_asm
|
||
{
|
||
mov edi, dest
|
||
mov ecx, count
|
||
shr ecx, 2
|
||
mov eax, value
|
||
rep stosd
|
||
}
|
||
}
|
||
|
||
// Sets 16-bit aligned memory.
|
||
void malloc_tsetword(void *dest, short value, int count){
|
||
_asm
|
||
{
|
||
mov edi, dest
|
||
mov ecx, count
|
||
shr ecx, 1
|
||
mov ax, value
|
||
rep stosw
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/*======================================
|
||
* Initialise
|
||
*--------------------------------------
|
||
*/
|
||
|
||
unsigned int malloc_usage (void)
|
||
{
|
||
#ifdef USE_MEMMGR
|
||
return memmgr_usage ();
|
||
#else
|
||
return 0;
|
||
#endif
|
||
}
|
||
|
||
void malloc_final (void)
|
||
{
|
||
#ifdef USE_MEMMGR
|
||
memmgr_final ();
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
void malloc_init (void)
|
||
{
|
||
#ifdef USE_MEMMGR
|
||
memmgr_init ();
|
||
#endif
|
||
return;
|
||
}
|