version 1.20, 2002/05/12 15:27:54
|
version 1.26, 2002/05/14 20:26:00
|
|
|
#include <windows.h> | #include <windows.h> |
#include <process.h> | #include <process.h> |
#include <stdio.h> | #include <stdio.h> |
|
#include <malloc.h> |
|
#include <stdlib.h> |
|
|
#elif defined (PEGASUS_PLATFORM_LINUX_IX86_GNU) | #elif defined (PEGASUS_PLATFORM_LINUX_IX86_GNU) |
#include <pthread.h> | #include <pthread.h> |
#include <semaphore.h> | #include <semaphore.h> |
|
|
#include <malloc.h> | #include <malloc.h> |
#include <errno.h> | #include <errno.h> |
#include <signal.h> | #include <signal.h> |
|
#include <new.h> |
namespace | namespace |
{ | { |
static const int GUARD_SIZE = 0x10; | static const int GUARD_SIZE = 0x10; |
|
|
static const unsigned int AVAIL = 0x00000002; | static const unsigned int AVAIL = 0x00000002; |
static const unsigned int ARRAY_NODE = 0x00000004; | static const unsigned int ARRAY_NODE = 0x00000004; |
static const unsigned int CHECK_FAILED = 0x00000008; | static const unsigned int CHECK_FAILED = 0x00000008; |
|
static const unsigned int ALREADY_DELETED = 0x00000010; |
|
static const unsigned int OVERWRITE = 0x00000020; |
|
static const unsigned int CHECK_LEAK = 0x00000040; |
|
static const unsigned int HUGE_NODE = 0x00000080; |
} | } |
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
class guardian; |
|
struct SUBALLOC_HANDLE; | struct SUBALLOC_HANDLE; |
| |
PEGASUS_SUBALLOC_LINKAGE void * pegasus_alloc(size_t); |
#if defined(PEGASUS_DEBUG_MEMORY) |
PEGASUS_SUBALLOC_LINKAGE void * pegasus_alloc(size_t, | PEGASUS_SUBALLOC_LINKAGE void * pegasus_alloc(size_t, |
void *, | void *, |
int type, | int type, |
const Sint8 *classname, | const Sint8 *classname, |
Sint8 *file, | Sint8 *file, |
Uint32 line ); | Uint32 line ); |
|
|
PEGASUS_SUBALLOC_LINKAGE void pegasus_free(void *dead, | PEGASUS_SUBALLOC_LINKAGE void pegasus_free(void *dead, |
void *, | void *, |
int type, | int type, |
Sint8 *classname, | Sint8 *classname, |
Sint8 *file, | Sint8 *file, |
Uint32 line); | Uint32 line); |
|
#else |
|
PEGASUS_SUBALLOC_LINKAGE void * pegasus_alloc(size_t); |
PEGASUS_SUBALLOC_LINKAGE void pegasus_free(void *); | PEGASUS_SUBALLOC_LINKAGE void pegasus_free(void *); |
|
#endif |
|
|
|
|
|
|
|
|
| |
#if defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC) | #if defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC) |
| |
|
|
| |
class peg_suballoc; | class peg_suballoc; |
| |
|
|
#if defined(PEGASUS_DEBUG_MEMORY) | #if defined(PEGASUS_DEBUG_MEMORY) |
#define PEGASUS_NEW(a) new((pegasus_alloc(sizeof(a), ((void *)0), NORMAL, (#a), __FILE__, __LINE__))) |
#define PEGASUS_NEW(a, h) new((pegasus_alloc(sizeof(a), ((void *)h), NORMAL, (#a), __FILE__, __LINE__))) |
#define PEGASUS_ARRAY_NEW(a, i) new(pegasus_alloc(sizeof(a) * (i), NULL, ARRAY, (#a), __FILE__, __LINE__)) (a) |
#define PEGASUS_ARRAY_NEW(a, i, h) new(pegasus_alloc(sizeof(a) * (i), ((void *)(h)), ARRAY, (#a), __FILE__, __LINE__)) a |
#define PEGASUS_DELETE(a) pegasus_free((a), NULL, NORMAL, (#a), __FILE__, __LINE__) | #define PEGASUS_DELETE(a) pegasus_free((a), NULL, NORMAL, (#a), __FILE__, __LINE__) |
#define PEGASUS_ARRAY_DELETE(a) pegasus_free(a, NULL, ARRAY, (#a), __FILE__, __LINE__) | #define PEGASUS_ARRAY_DELETE(a) pegasus_free(a, NULL, ARRAY, (#a), __FILE__, __LINE__) |
|
#define PEGASUS_CHECK_FOR_LEAKS(h) peg_suballocator::get_instance()->_UnfreedNodes((h)) |
|
#define PEGASUS_START_LEAK_CHECK() peg_suballocator::get_instance()->set_leak_mode(true) |
|
#define PEGASUS_STOP_LEAK_CHECK() peg_suballocator::get_instance()->set_leak_mode(false) |
#else | #else |
#define PEGASUS_NEW(a) new |
#define PEGASUS_NEW(a, h) new |
#define PEGASUS_ARRAY_NEW(a, i) new (a)[(i)] |
#define PEGASUS_ARRAY_NEW(a, i, h) new a[(i)] |
#define PEGASUS_DELETE(a) ::operator delete((a)) |
#define PEGASUS_DELETE(a) delete((a)) |
#define PEGASUS_ARRAY_DELETE(a) ::operator delete [] ((a)) |
#define PEGASUS_ARRAY_DELETE(a) delete [] ((a)) |
|
#define PEGASUS_CHECK_FOR_LEAKS(h) |
|
#define PEGASUS_START_LEAK_CHECK() |
|
#define PEGASUS_STOP_LEAK_CHECK() |
#endif | #endif |
| |
| |
|
|
struct _subAllocNode *prev; | struct _subAllocNode *prev; |
Uint32 flags; | Uint32 flags; |
Uint32 allocSize; | Uint32 allocSize; |
|
Uint32 nodeSize; |
|
void *concurrencyHandle; |
|
#if defined(PEGASUS_DEBUG_MEMORY) |
Sint8 file[MAX_PATH_LEN + 1]; | Sint8 file[MAX_PATH_LEN + 1]; |
Sint8 line[MAX_LINE_LEN + 1]; |
Uint32 line; |
Sint8 classname[MAX_CLASS_LEN + 1]; | Sint8 classname[MAX_CLASS_LEN + 1]; |
Sint8 d_file[MAX_PATH_LEN + 1]; | Sint8 d_file[MAX_PATH_LEN + 1]; |
Sint8 d_line[MAX_LINE_LEN + 1]; |
Uint32 d_line; |
Sint8 d_classname[MAX_CLASS_LEN + 1]; | Sint8 d_classname[MAX_CLASS_LEN + 1]; |
void *concurrencyHandle; |
|
Uint8 guardPre[GUARD_SIZE]; | Uint8 guardPre[GUARD_SIZE]; |
|
#endif |
} SUBALLOC_NODE; | } SUBALLOC_NODE; |
| |
SUBALLOC_NODE *nodeListHeads[3][16]; | SUBALLOC_NODE *nodeListHeads[3][16]; |
|
|
PEGASUS_MUTEX_T init_mutex; | PEGASUS_MUTEX_T init_mutex; |
Boolean debug_mode; | Boolean debug_mode; |
Boolean abort_on_error; | Boolean abort_on_error; |
|
Boolean check_for_leaks; |
| |
public: | public: |
static int CREATE_MUTEX(PEGASUS_MUTEX_T *mut); | static int CREATE_MUTEX(PEGASUS_MUTEX_T *mut); |
|
|
SUBALLOC_NODE *GetHugeNode(Sint32 size); | SUBALLOC_NODE *GetHugeNode(Sint32 size); |
void PutNode(Sint32 vector, Sint32 index, SUBALLOC_NODE *node); | void PutNode(Sint32 vector, Sint32 index, SUBALLOC_NODE *node); |
void PutHugeNode(SUBALLOC_NODE *node); | void PutHugeNode(SUBALLOC_NODE *node); |
|
#if defined(PEGASUS_DEBUG_MEMORY) |
static const Uint8 guard[]; | static const Uint8 guard[]; |
static const Uint8 alloc_pattern; | static const Uint8 alloc_pattern; |
static const Uint8 delete_pattern; | static const Uint8 delete_pattern; |
|
|
static Boolean _CheckGuard(SUBALLOC_NODE *); | static Boolean _CheckGuard(SUBALLOC_NODE *); |
| |
| |
|
static Uint32 _CheckNode(void *m); |
|
SUBALLOC_NODE *_CheckNode(void *m, int type, Sint8 *file, Uint32 line); |
|
public: |
|
static Uint32 CheckMemory(void *); |
|
#endif |
public: | public: |
| |
peg_suballocator(void); | peg_suballocator(void); |
|
|
| |
Boolean InitializeSubAllocator(void); | Boolean InitializeSubAllocator(void); |
static SUBALLOC_HANDLE *InitializeProcessHeap(Sint8 *f = NULL); | static SUBALLOC_HANDLE *InitializeProcessHeap(Sint8 *f = NULL); |
|
#if defined(PEGASUS_DEBUG_MEMORY) |
void *vs_malloc(size_t size, void *handle, int type = NORMAL, const Sint8 *classname = 0, const Sint8 *f = 0, Uint32 l = 0); | void *vs_malloc(size_t size, void *handle, int type = NORMAL, const Sint8 *classname = 0, const Sint8 *f = 0, Uint32 l = 0); |
void *vs_calloc(size_t num, size_t size, void *handle, int type = NORMAL, Sint8 *f = 0, Uint32 l = 0); | void *vs_calloc(size_t num, size_t size, void *handle, int type = NORMAL, Sint8 *f = 0, Uint32 l = 0); |
void *vs_realloc(void *pblock, size_t newsize, void *handle, int type = NORMAL, Sint8 *f = 0, Uint32 l = 0); | void *vs_realloc(void *pblock, size_t newsize, void *handle, int type = NORMAL, Sint8 *f = 0, Uint32 l = 0); |
Sint8 * vs_strdup(const Sint8 *string, void *handle, int type = NORMAL, Sint8 *f = 0, Uint32 l = 0); | Sint8 * vs_strdup(const Sint8 *string, void *handle, int type = NORMAL, Sint8 *f = 0, Uint32 l = 0); |
void vs_free(void *m); |
|
void vs_free(void *m, void *handle, int type, Sint8 *classname, Sint8 *f, Uint32 l); | void vs_free(void *m, void *handle, int type, Sint8 *classname, Sint8 *f, Uint32 l); |
Boolean _UnfreedNodes(void *handle); | Boolean _UnfreedNodes(void *handle); |
|
Boolean get_mode(void) { return debug_mode; } |
|
void set_leak_mode(Boolean mode) { check_for_leaks = mode; } |
|
#else |
|
void *vs_malloc(size_t size); |
|
void *vs_calloc(size_t num, size_t size); |
|
void *vs_realloc(void *pblock, size_t newsize); |
|
Sint8 *vs_strdup(const Sint8 *str); |
|
void vs_free(void *m); |
|
Boolean get_mode(void) { return false; } |
|
void set_leak_mode(Boolean mode) { } |
|
#endif |
void DeInitSubAllocator(void *handle); | void DeInitSubAllocator(void *handle); |
SUBALLOC_NODE *_CheckNode(void *m, int type, Sint8 *file, Uint32 line); |
static peg_suballocator *get_instance(void); |
|
SUBALLOC_HANDLE & get_handle(void) { return internal_handle; } |
Boolean get_mode(void) |
|
{ |
|
return debug_mode; |
|
} |
|
|
|
SUBALLOC_HANDLE & get_handle(void) |
|
{ |
|
return internal_handle; |
|
} |
|
|
|
private: | private: |
_suballocHandle internal_handle; | _suballocHandle internal_handle; |
|
static peg_suballocator *_suballoc_instance; |
|
|
}; | }; |
| |
inline Boolean peg_suballocator::IS_ARRAY(SUBALLOC_NODE *x) | inline Boolean peg_suballocator::IS_ARRAY(SUBALLOC_NODE *x) |
|
|
#endif /* SUBALLOC_INCLUDE */ | #endif /* SUBALLOC_INCLUDE */ |
| |
| |
// how to debug a specific object: |
|
// add an operator new to the object such that |
|
// void * operator new(size_t size, peg_suballocator::_sub_handle = 0); |
|
// void operator delete(void *dead, size_t size); |
|
// have operator delete check for unfreed nodes by calling sub->unfreed_nodes |
|
|
|