⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmem.c

📁 Extended C/C++ Dynamic Memory Control And Debug Library
💻 C
📖 第 1 页 / 共 5 页
字号:
 /* linear address = segment * 16 + offset */
  #define XMEM_LIN_ADDR(p)   ((((UNS32)(p) & 0xffff0000L) >> 12) + ((UNS32)(p) & 0x0000ffffL))
  #pragma message("XMEM_LIN_ADDR(p) for LARGE model")
 #elif M_I86SM || __SMALL__      /**** small model: 2 byte pointer ****/
  #define XMEM_LIN_ADDR(p)   ((UNS32)(p) & 0x0000ffffL)
  #pragma message("XMEM_LIN_ADDR(p) for SMALL model")
 #else
  #error unsupported memory model, only SMALL or LARGE model are implemented
 #endif
#else                           /**** flat model, linear address space ****/
 #define XMEM_LIN_ADDR(p)    (PTRCAST)(p) /* pointer is already linear */
 #pragma message("XMEM_LIN_ADDR(p) for flat model/linear address space")
#endif

/* Note: the following check does not always work because 
   sizeof() is only supported by some preprocessors.
   Therefore it is disabled */
/*
#if sizeof(void *) > sizeof(UNS32)
#error unsupported pointer size
#endif
*/

/**** source code location of function calls ****/
#if XMEM_WHERE                      /* print source location */
 #define MEM_LOCATE_TEXT(a,x,y,z,b) xmem_printf("%s '%s()' <%s,%lu>%s", (char *)(a),    \
                                                (char *)((x) ? (x) : FUNCTION_UNKNOWN), \
                                                (char *)((y) ? (y) : FILENAME_UNKNOWN), \
                                                (unsigned long)z, (char *)(b));
 #define MEM_LOCATE(x,y,z)          MEM_LOCATE_TEXT("",x,y,z,"")
#else
 #define MEM_LOCATE_TEXT(a,x,y,z,b)
 #define MEM_LOCATE(x,y,z)
#endif          /* XMEM_WHERE */

/**** source location of last visit in any XMEM trace function ****/
#if XMEM_WHERE && XMEM_VISIT    /* remember source location for last visit */
 #define LAST_VISIT()           xmem_printf(" [last XMEM visit at %s() <%s,%lu>]",                            \
                                            (char *)((visit_callname) ? (visit_callname) : FUNCTION_UNKNOWN), \
                                            (char *)((visit_fname) ? (visit_fname) : FILENAME_UNKNOWN),       \
                                            (unsigned long)visit_line);
#define THIS_VISIT(x,y,z)      { visit_callname = ((x) ? (x) : FUNCTION_UNKNOWN); \
                                 visit_fname = ((y) ? (y) : FILENAME_UNKNOWN);    \
                                 visit_line = (z); }
#else
 #define LAST_VISIT()
 #define THIS_VISIT(x,y,z)
#endif          /* XMEM_WHERE && XMEM_VISIT */

/**** string length limit ****/
#define XMEM_STREOS_LIMIT       4000    /* warn, if EOS not within limit (change limit value if necessary) */

/**** GNU specific things ****/
#if __GNUC__
 char *strrev(char *);
 int strcmpi(const char *, const char *);
#endif
#if GNUTEST                     /* just to satisfy prototyping (GNU-C 2.2.2) */
 int memicmp(const void *, const void *, unsigned int);
 int stricmp(const char *, const char *);
#endif

#define OBJ_ARR_LEN_OFFS        4   /* object array length offset for new[] and delete[] */

/*****************************************************************************/
/*****************************************************************************/
/* local types */
/*****************************************************************************/
/*****************************************************************************/
#if XMEM_CALLSTACK
/* this part is Microsoft specific */
struct _s_callstack_entry       /* one call stack frame */
{
  SGN08  *funcname;             /* function name */
  SGN08  *filename;             /* filename */
  UNS32   lineno;               /* line number */
  DWORD64 offset;               /* address offset */
};
typedef struct _s_callstack_entry  S_CALLSTACK_ENTRY;

#define MAX_CALLSTACK   15      /* number of stack frames being handled */

struct _s_callstack             /* wrapper structure for all stack frames */
{
  S_CALLSTACK_ENTRY   entry[MAX_CALLSTACK];
};
typedef struct _s_callstack        S_CALLSTACK;
#endif          /* endif XMEM_CALLSTACK */

struct _s_allocation
{
  size_t size;                /* size of memory block, including overhead */
  UNS32  alloc_nr;            /* allocation # */
  UNS32  free_nr;             /* free # */
  SGN32  scope_level;         /* scope # */
  void  *ptr;                 /* pointer to memory block */
  void  *freed;               /* pointer to freed memory block */
  SGN08 *funcname;            /* name of alloc function */
#if XMEM_WHERE
  const SGN08 *cname;         /* name of calling function */
  const SGN08 *fname;         /* filename where initial allocation occured */
  const SGN08 *realloc_cname; /* name of calling function where realloc occured */
  const SGN08 *realloc_fname; /* filename where realloc occured */
  const SGN08 *free_cname;    /* name of calling function where final free occured */
  const SGN08 *free_fname;    /* filename where final free occured */
  UNS32  line;                /* line number where initial allocation occured */
  UNS32  realloc_line;        /* line number where realloc occured */
  UNS32  free_line;           /* line number where final free occured */
#endif
#if defined(_MSC_VER)
  struct _timeb   timebuf;    /* allocation time */
#else
  time_t          ltime;      /* allocation time */
#endif
#if XMEM_CALLSTACK
  S_CALLSTACK     cstk;         /* call stack */
  S_CALLSTACK     realloc_cstk; /* call stack */
  S_CALLSTACK     free_cstk;    /* call stack */
#endif
};
typedef struct _s_allocation S_ALLOCATION;

struct _s_slot
{
  struct _s_slot *next;         /* pointer to next slot in sub-linked list */
  UNS16           entries;      /* number of entries in this sub-linked list */
  S_ALLOCATION   *alloc;        /* pointer to allocation trace block */
};
typedef struct _s_slot S_SLOT;

struct _s_scope
{
  const SGN08 *scope_cname;     /* scope function name */
  const SGN08 *scope_fname;     /* scope filename */
  UNS32        scope_line;      /* scope linen number */
};
typedef struct _s_scope S_SCOPE;

#if XMEM_WHERE
struct _s_functions
{
  struct _s_functions *next;        /* link to next element */
  const SGN08         *callname;    /* functionname */
  UNS32                count;       /* usage counter */
};
typedef struct _s_functions S_FUNCTIONS;

struct _s_files
{
  struct _s_files     *next;        /* link to next element */
  const SGN08         *filename;    /* filename */
  UNS32                count;       /* usage counter */
  struct _s_functions *root;        /* link to funtions within this file */
};
typedef struct _s_files S_FILES;

static void     xmem_add_callname(S_FILES *pfiles, const SGN08 *callname);
static void     xmem_add_filename_callname(const SGN08 *filename, const SGN08 *callname);
#endif      /* XMEM_WHERE */

/*****************************************************************************/
/*****************************************************************************/
/* local variables */
/*****************************************************************************/
/*****************************************************************************/
static S_SLOT **ptrhash = (S_SLOT **)NULL;  /**** hash table root entry ****/

static BOOLEAN flag_ptrhash = FALSE;        /* flag to indicate repeated hash table allocation */

static UNS16 memtrace = XMEM_TRACE;         /* memory trace control variable */
static UNS16 memtrace_save = 0;
static UNS16 memtrace_realloc = FALSE;      /* memory trace control variable */
static UNS16 memtrace_realloc_save = 0;
static UNS16 inside_realloc = FALSE;        /* flag for realloc */

static size_t xmem_max_heapsize  = (size_t)-1;/* maximum allowed heapsize */
#if XMEM_STRESS
static UNS16 xmem_stress_ratio  = 0;        /* stress ratio in [%] (0...100) */
#endif

struct _s_counters
{
  size_t sum_progmem;           /* overall # of bytes allocated */
  size_t act_progmem;           /* actual # of bytes allocated */
  size_t total_progmem;         /* maximum # of bytes allocated from program */
  size_t total_memory;          /* total # of bytes allocated */
  UNS32 total_alloc;            /* # of alloc calls, program + memcontrol */
  UNS32 total_progalloc;        /* # of alloc calls from program, done */
  UNS32 total_alloc_call;       /* # of alloc calls from program */
  UNS32 total_realloc_call;     /* # of alloc calls from program */
  UNS32 total_expand_call;      /* # of alloc calls from program */
  UNS32 total_free;             /* # of free calls, program + memcontrol */
  UNS32 total_progfree;         /* # of free calls from program, done */
  UNS32 total_free_call;        /* # of free calls from program */
  UNS32 total_realloc_NULL;     /* # of reallo calls with NULL */
  UNS32 total_expand_NULL;      /* # of _expand calls with NULL */
  UNS32 malloc_call;            /* # of calls */
  UNS32 calloc_call;            /* # of calls */
  UNS32 realloc_call;           /* # of calls */
  UNS32 expand_call;            /* # of calls */
  UNS32 alloca_call;            /* # of calls */
  UNS32 free_call;              /* # of calls */
  UNS32 new_call;               /* # of calls */
  UNS32 new_array_call;         /* # of calls */
  UNS32 delete_call;            /* # of calls */
  UNS32 delete_array_call;      /* # of calls */
  UNS32 strdup_call;            /* # of calls */
};
typedef struct _s_counters S_COUNTERS;

static S_COUNTERS counters;                 /* statistics */

#define SUB_LIMIT(x,y)          (((x) > (y)) ? ((x) - (y)) : 0)

#if XMEM_WHERE && XMEM_VISIT
static const SGN08 *visit_callname = NULL;
static const SGN08 *visit_fname = NULL;
static UNS32 visit_line = 0;
#endif

static UNS16 trace_alloc_flag = FALSE;
static UNS32 trace_alloc_nr = 0;
static UNS16 trace_free_flag = FALSE;
static UNS32 trace_free_nr = 0;

#if XMEM_WHERE
static S_FILES     *pfiles_root = NULL;
#endif

#define SCOPE_DEPTH             20          /* initial scope nesting depth */
static SGN32 scope_level = 0;               /* actual scope level (= array index) */
static SGN32 scope_depth = 0;               /* actual maximum scope depth */
static S_SCOPE *scope_stack = NULL;         /* the scope stack array */

static const SGN08 *loc_cname = FUNCTION_UNKNOWN;   /* call name */
static const SGN08 *loc_fname = FILENAME_UNKNOWN;   /* function name */
static UNS32 loc_line = 0;                  /* line number */

#if XMEM_LOGFILE                            /* logfile for memory function call tracing */
 static FILE *p_xmem_logfile = NULL;
 static const char *xmem_logfilename = "xmem.log";            /* the logfile filename */
 static UNS32 xmem_logcount = 0;
 #if XMEM_HTMLLOGFILE
  static FILE *p_xmem_htmllogfile = NULL;
  static const char *xmem_htmllogfilename = "xmem_log.html";  /* the HTML filename */
 #endif
#endif
#if XMEM_ERRLOGFILE                         /* logfile for error messages */
 static FILE *p_xmem_errlogfile = NULL;
 static const char *xmem_errlogfilename = "xmem_err.log";    /* the errorlogfile filename */
#endif

static BOOLEAN B_do_print = TRUE;
static BOOLEAN B_do_log = TRUE;

/**** operator delete stack ****/
#ifdef __cplusplus
#if XMEM_CPP_DELETE_STACK
#define XMEM_DELETE_STACK_SIZE          300
static S_SCOPE xmem_delete_stack[XMEM_DELETE_STACK_SIZE];
static SGN32   xmem_delete_stack_count = 0;
int xmem_delete_lock = 0;
#endif
#endif

/**** calculate the allocation limit for given type "size_t": 2^(sizeof(size_t) * 8) - 1 ****/
/* this works for all sizes of size_t and for all pointer sizes */
/* do it "by hand" to avoid including "math.h" */
static double get_alloc_limit(void)
{
  unsigned int exponent = sizeof(size_t) * 8; /* (number of bytes) * ((number of bits) / byte) */
  double pow2;
  for (pow2 = 1.0; exponent > 0; --exponent)
  {
    pow2 *= 2.0;
  }
  return(pow2 - 1.0);
}
static double alloc_limit = 0.0;        /* the "natural" allocation limit: */
                                        /* maximum value that can be stored in a "size_t" value */

/**** for the statistical purposes ****/
#if XMEM_STATS          /* array for statistical calculations (histogram) */
/* categories: 0, <=5, <=10, <=50, <=100, <=500, <=1000, <=5000, <=10000, */
/*             <=50000, <=100000, <=500000, <=1000000, >1000000 */
#define STATSLOTS       14

struct _s_stats
{
  UNS32 stats[STATSLOTS];
};
typedef struct _s_stats S_STATS;

static S_STATS stats = { { 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L } };
#endif

#if XMEM_STATS
static void xmem_statistics(size_t size);
#endif

/**** some SXT specific internal settings ****/
#if GNUCPP      /* GNUCPP */
 #ifdef XMEM_SXT
  #undef XMEM_SXT
 #endif
 #define XMEM_SXT   1
#endif          /* GNUCPP */

#if XMEM_SXT    /* XMEM_SXT */
#ifdef __cplusplus
extern "C" {
#endif
extern unsigned long  memory_allocated;         /* currently allocated memory */
extern unsigned long  memory_total_allocated;   /* total allocated memory */
extern unsigned long  memory_max_allocated;     /* maximum allocated memory */
extern unsigned long  memory_alloc_calls;       /* number of memory allocation calls */
extern unsigned long  memory_free_calls;        /* number of memory free calls */
#ifdef __cplusplus
}
#endif
#endif          /* XMEM_SXT */
/**** END OF some SXT specific internal settings ****/

/**** for XMEM_ALLOC_CALL (call redirection with detours) ****/
#if XMEM_ALLOC_CALL
static SGN32    xmem_call_internal = FALSE;
static BOOLEAN  xmem_call_init = FALSE;
static BOOLEAN  xmem_call_quiet = FALSE;
static void     xmem_call_setup(void);
static void     xmem_call_shutdown(void);
#define XMEM_CALL_INTERNAL_LOCK()   ++xmem_call_internal    /* set flag to avoid recursion */
#define XMEM_CALL_INTERNAL_UNLOCK() --xmem_call_internal;   /* reset flag to avoid recursion */ \
                                    if (xmem_call_internal < 0)                                 \
                                    { xmem_printf("\nWARNING: internal call unlock underflow"); xmem_call_internal = 0; }
#else
#define XMEM_CALL_INTERNAL_LOCK()
#define XMEM_CALL_INTERNAL_UNLOCK()
#endif

/**** for XMEM_ALLOC_LIB (library call interception) ****/
#if XMEM_ALLOC_LIB
static BOOLEAN  xmem_lib_init = FALSE;          /* XMEM lib initialization status */
static BOOLEAN  xmem_lib_quiet = TRUE;          /* quiet mode, no call to output functions */
static void     xmem_lib_setup(void);

#if _DEBUG      /* Microsoft specific _xxx_dbg functions */
 #define DBG_PARAMS_PROTO   , int, const char *, int
 #define DBG_PARAMS         , _NORMAL_BLOCK, __FILE__, (int)__LINE__
#else           /**/
 #define DBG_PARAMS_PROTO
 #define DBG_PARAMS
#endif          /**/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -