📄 xmem.c
字号:
#pragma message("XMEM 4 byte / 32 bit pointer -> XMEM_32BIT")
#elif (__linux__ && __x86_64__) /* Linux 64 bit */
#define PTRFMT "%016lx" /* 8 byte / 64 bit pointer size */
#define PTRCAST ptrdiff_t /* ??? */
#define XMEM_64BIT 1
#pragma message("XMEM 8 byte / 64 bit pointer -> XMEM_64BIT")
#elif __linux__ /* Linux 32 bit */
#define PTRFMT "%08lx" /* 4 byte / 32 bit pointer size */
#define PTRCAST unsigned long /* only this works ... */
#define XMEM_32BIT 1
#pragma message("XMEM 4 byte / 32 bit pointer -> XMEM_32BIT")
#elif __GNUC__ /* GNU C/C++ (DJGPP) */
#define PTRFMT "%08lx" /* 4 byte / 32 bit pointer size */
#define PTRCAST ptrdiff_t
#define XMEM_32BIT 1
#pragma message("XMEM 4 byte / 32 bit pointer -> XMEM_32BIT")
#else /* unknown compiler / target */
#define PTRFMT "%08lx" /* 4 byte / 32 bit pointer size */
#define PTRCAST long
#define XMEM_32BIT 1
#pragma message(">>>> XMEM unknown pointer size, assuming 4 byte / 32 bit pointer -> XMEM_32BIT <<<<")
#endif
/*****************************************************************************/
/* */
/*****************************************************************************/
#if __GNUC__ || (_WIN32 && (_MSC_VER < 1100))
#if XMEM_TEST_MCB
#pragma message(">>> XMEM_TEST_MCB disabled!!!")
#endif
#undef XMEM_TEST_MCB
#define XMEM_TEST_MCB 0 /* actually only MS-C and Borland C, otherwise not possible */
#endif
/*****************************************************************************/
/*****************************************************************************/
/* local XMEM functions */
/*****************************************************************************/
/*****************************************************************************/
void *xmem_store_pointer(void *, size_t, SGN08 * _WHERE(const SGN08 *, const SGN08 *, UNS32));
#if XMEM_ASPECTCPP && !XMEM_WHERE
void *xmem_store_pointer(void *, size_t, SGN08 *, const SGN08 *, const SGN08 *, UNS32);
#endif
void xmem_delete_pointer(void *, SGN08 * _WHERE(const SGN08 *, const SGN08 *, UNS32));
#if XMEM_ASPECTCPP && !XMEM_WHERE
void xmem_delete_pointer(void *, SGN08 *, const SGN08 *, const SGN08 *, UNS32);
#endif
void *xmem_find_ptr(void *);
static size_t xmem_get_size(void *);
static UNS32 xmem_get_allocation_id(void *);
static void xmem_test_ptr(void *, SGN08 * _WHERE(const SGN08 *, const SGN08 *, UNS32));
static void xmem_test_guard(void *, size_t, UNS32, UNS32, SGN08 * _WHERE(const SGN08 *, const SGN08 *, UNS32)
_WHERE(const SGN08 *, const SGN08 *, UNS32));
#if (!XMEM_QUIET || XMEM_FORCE_OUTPUT) && (XMEM_STR || XMEM_MEM || XMEM_FILE)
#if 0
static void xmem_test_overflow(void *, size_t, SGN08 * _WHERE(const SGN08 *, const SGN08 *, UNS32));
#endif
static void xmem_test_boundary(void *, size_t, SGN08 * _WHERE(const SGN08 *, const SGN08 *, UNS32));
#endif
#if (!XMEM_QUIET || XMEM_FORCE_OUTPUT) && XMEM_STR && XMEM_STREOS
static void xmem_test_string(SGN08 *, SGN08 * _WHERE(const SGN08 *, const SGN08 *, UNS32));
#endif
static void *xmem_alloc_pointer(size_t, SGN08 * _WHERE(const SGN08 *, const SGN08 *, UNS32));
static void xmem_free_pointer(void *, SGN08 * _WHERE(const SGN08 *, const SGN08 *, UNS32));
static void xmem_find_change(void *, void *, size_t);
#if !XMEM_QUIET || XMEM_FORCE_OUTPUT
static BOOLEAN xmem_test_used(UNS08 *, size_t);
#endif
static BOOLEAN xmem_test_size(size_t _WHERE(const SGN08 *, const SGN08 *, UNS32));
#if XMEM_TEST_MCB
static BOOLEAN xmem_test_mcb(void *, size_t _WHERE(const SGN08 *, const SGN08 *, UNS32));
#endif
#if XMEM_TEST_NULL
static void xmem_test_null(void *, size_t _WHERE(const SGN08 *, const SGN08 *, UNS32));
#endif
static void xmem_internal_null(void);
#if XMEM_STRESS
static BOOLEAN xmem_stressed(void);
#endif
static void xmem_check_scope(const SGN08 *callname, const SGN08 *fname, UNS32 line);
#if XMEM_STREOS
#define XMEM_TEST_STRING(a) xmem_test_string a
#else
#define XMEM_TEST_STRING(a)
#endif
/*****************************************************************************/
/*****************************************************************************/
/* output redirection */
/*****************************************************************************/
/*****************************************************************************/
static int xmem_printf(const char *, ...); /* the XMEM printf() */
#if !XMEM_QUIET || XMEM_FORCE_OUTPUT || XMEM_OUTPUTDEBUGSTRING
#define XMEM_MSG_BUFLEN 4000
static char xmem_msg_buffer[XMEM_MSG_BUFLEN]; /* large text buffer */
#endif
#if UNICODE
#define PTR2STR LPCWSTR
#else
#define PTR2STR LPCSTR
#endif
#if !_WINDOWS /**** not WINDOWS ****/
#if _WIN32
#if XMEM_OUTPUTDEBUGSTRING
static void (__stdcall *xmem_output_function)(PTR2STR) = OutputDebugString;
#else
static void (__stdcall *xmem_output_function)(PTR2STR) = NULL;
#endif
#endif
#if !XMEM_QUIET || XMEM_FORCE_OUTPUT
static int (*xmem_output_function_int_vararg)(const char *, ...) = printf;
static void (*xmem_output_function_void_vararg)(const char *, ...) = NULL;
#endif
#else /**** WINDOWS ****/
#if XMEM_OUTPUTDEBUGSTRING
static void (__stdcall *xmem_output_function)(const char *) = OutputDebugString;
#else
static void (__stdcall *xmem_output_function)(const char *) = NULL;
#endif
#if !XMEM_QUIET || XMEM_FORCE_OUTPUT
static int (*xmem_output_function_int_vararg)(const char *, ...) = NULL;
static void (*xmem_output_function_void_vararg)(const char *, ...) = NULL;
#endif
#endif /**** WINDOWS ****/
#if XMEM_CALLTRACE /* XMEM function call trace */
#define TRACEPRT(a) xmem_printf a
#define TRACELOC(a) MEM_LOCATE a
#if !XMEM_QUIET || XMEM_FORCE_OUTPUT
#define TRACEFFLUSH() fflush(stdout)
#else
#define TRACEFFLUSH()
#endif
#else /* no XMEM function call trace */
#define TRACEPRT(a)
#define TRACELOC(a)
#define TRACEFFLUSH()
#endif /* XMEM_CALLTRACE */
#if !XMEM_QUIET || XMEM_FORCE_OUTPUT
#define FFLUSH() fflush(stdout)
#else
#define FFLUSH()
#endif
/*****************************************************************************/
/*****************************************************************************/
/* XMEM logfile */
/*****************************************************************************/
/*****************************************************************************/
#if XMEM_LOGFILE
static void xmem_logfile(SGN08 *, PTRCAST, size_t, UNS32 _WHERE(const SGN08 *, const SGN08 *, UNS32));
#define LOGFILE(a) xmem_logfile a
#else
#define LOGFILE(a)
#endif
#define LOGFILE_ERROR_TRACE 0
/*****************************************************************************/
/*****************************************************************************/
/* XMEM dialog */
/*****************************************************************************/
/*****************************************************************************/
#if XMEM_DIALOG
#define XMEM_COLLECT_DIALOG() xmem_collect_dialog()
#define XMEM_SHOW_DIALOG() xmem_show_dialog()
static void xmem_collect_dialog(void);
static void xmem_show_dialog(void);
#define XMEM_DIALOG_BUFLENGTH 20000
static SGN08 dialog_buffer[XMEM_DIALOG_BUFLENGTH + 1];
static BOOLEAN flag_collect_dialog = FALSE;
static BOOLEAN flag_show_dialog = TRUE;
#else
#define XMEM_COLLECT_DIALOG()
#define XMEM_SHOW_DIALOG()
#endif
/*****************************************************************************/
/*****************************************************************************/
/* XMEM Browser */
/*****************************************************************************/
/*****************************************************************************/
#if XMEM_BROWSER
#define XMEM_MSG_COUNTERS 1
#define XMEM_MSG_STATS 2
#define XMEM_MSG_TEXT 3
#define XMEM_MSG_LOG 4
void xmem_send_msg(UNS32);
#define xmem_send_counters() xmem_send_msg(XMEM_MSG_COUNTERS)
#define xmem_send_stats() xmem_send_msg(XMEM_MSG_STATS)
#define xmem_send_text() xmem_send_msg(XMEM_MSG_TEXT)
#define xmem_send_log() xmem_send_msg(XMEM_MSG_LOG)
#else
#define xmem_send_counters()
#define xmem_send_stats()
#define xmem_send_text()
#define xmem_send_log()
#endif
/*****************************************************************************/
/*****************************************************************************/
/* local defines */
/*****************************************************************************/
/*****************************************************************************/
#ifndef XMEM_TRACE
/**** XMEM_TRACE is used for the selection of the XMEM memory trace type ****/
#define XMEM_TRACE 1 /* 0 == off */
/* 1 == memory trace */
/* 2 == memory trace with alloc copy, will catch later overwrites */
/* NOTE: XMEM_TRACE == 2 and XMEM_FREENULL != 0 makes no sense because the */
/* freed pointer will point to NULL and not to the freed memory block ! */
#endif /* XMEM_TRACE */
#if XMEM_PEDANTIC /* perform numerous checks in all functions (quite pedantic) */
#define CHECKPOINT() xmem_overwrite(FUNCTION_UNKNOWN,"internal",0)
#else
#define CHECKPOINT()
#endif /* XMEM_PEDANTIC */
/**** trace for user selected breaks ****/
#define TRACE_NUMBERS 1
/**** free leaking blocks by increasing number ****/
#ifndef XMEM_FREE_INCREASE_ORDER
#define XMEM_FREE_INCREASE_ORDER 1
#endif
/**** test for failed allocation ****/
#if !XMEM_TEST_NULL /* if no NULL test, remove function calls */
#if XMEM_WHERE
#define xmem_test_null(a, b, c, d, e)
#else
#define xmem_test_null(a, b)
#endif
#endif /* !XMEM_TEST_NULL */
/**** HASH values ****/
#if !__GNUC__ && !_WIN32
#define XMEM_HASHSIZE 29 /* must be odd number, best choice is prime */
/* (13, 23, 29, 31, 61, 127, 251, ...) */
/* smaller values: lower memory consumption */
/* larger values: faster execution */
#define SLOTSIZE 8
#else
#define XMEM_HASHSIZE 61 /* use larger values for 32 bit compilers */
#define SLOTSIZE 16
#endif
#if (XMEM_HASHSIZE % 2) == 0 /* check hash size value for correctness */
#error XMEM_HASHSIZE must be odd number!
#endif
#if 1 /* hash value calculation with macro */
#define HASHVALUE(p) ((PTRCAST)(p) % XMEM_HASHSIZE) /* quite simple calculation with modulo operation */
#else /* hash value calculation with function */
UNS32 hashvalue(void *p)
{
UNS32 value;
value = (((UNS32)(p)) % XMEM_HASHSIZE); /* quite simple calculation with modulo operation */
return(value);
}
#define HASHVALUE(p) hashvalue(p)
#endif
/**** overhead regions (guarding "fence") before and after memory block ****/
#if XMEM_GUARD
#ifndef OVHDBEG
#define OVHDBEG 8 /* should be multiple of natural alignment (4, 8, ?) */
#endif
#ifndef OVHDEND
#define OVHDEND 8 /* should be multiple of natural alignment (4, 8, ?) */
#endif
#pragma message("XMEM_GUARD enabled")
#else /* no guard region */
#define OVHDBEG 0 /* no guarding regions */
#define OVHDEND 0 /* no guarding regions */
#endif /* XMEM_GUARD */
#if ((OVHDBEG) < 0) || ((OVHDEND) < 0)
#error overhead value < 0
#endif
#if ((OVHDBEG) % 4) || ((OVHDEND) % 4)
#error overhead size alignment incorrect, should be 4 or multiple of 4
#endif
#define OVHDSIZE ((OVHDBEG) + (OVHDEND)) /* total overhead added */
#if (OVHDBEG > 0)
#define CLEAR_OVHDBEG(a,b,c) memset(a,b,c)
#else
#define CLEAR_OVHDBEG(a,b,c)
#endif
#if (OVHDEND > 0)
#define CLEAR_OVHDEND(a,b,c) memset(a,b,c)
#else
#define CLEAR_OVHDEND(a,b,c)
#endif
/**** pattern characters for allocated regions ****/
/**** NOTE: 0x00 or 0xff are not a good choice! ****/
#define BEGFILLCHAR 0x9D /* before allocated area */
#define ENDFILLCHAR 0xD9 /* after allocated area */
#define ALLOCFILLCHAR 0xFB /* allocated area */
#define FREEFILLCHAR 0xFD /* freed area */
#if !__GNUC__ && !_WIN32
#define TEST_SIZE 1 /* test requested allocation size for 64k limit */
/* only useful for 16 bit systems */
#else
#define TEST_SIZE 1 /* test requested allocation size for 2^32-1 limit */
/* only useful for 32 bit systems, assumes that */
/* 'size_t' = 'unsigned int' = 32 bit */
#endif
/**** memory control blocks (MCB) ****/
#if XMEM_TEST_MCB
#define xmem_test_mcb_(a) xmem_test_mcb a
#if defined(_MSC_VER)
#if !_WIN32
#define MCB_MEMSIZE(p) *((unsigned int *)((char *)(p) - 2)) /* Microsoft */
#elif _MSC_VER >= 1100
#define MCB_MEMSIZE(p) _msize(p) /* Microsoft */
#elif _MSC_VER < 1100
#error MCB functionality requires MS VC++ 5.0 or higher
#endif
#elif __TURBOC__
#define MCB_MEMSIZE(p) *((unsigned int *)((char *)(p) - 4)) /* Turbo C++ */
#else
#error MCB_MEMSIZE: unknown compiler
#endif
#else /* XMEM_TEST_MCB */
#define xmem_test_mcb_(a) 0 /* undefine it */
#endif /* XMEM_TEST_MCB */
/**** address calculation macros ****/
#if !__GNUC__ && !_WIN32
#if M_I86LM || __LARGE__ /**** large model: 4 byte pointer ****/
/* calculate linear adress from segment:offset pointer value (MS-DOS) */
/* 2 byte segment, 2 byte offset */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -