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

📄 xmem.c

📁 Extended C/C++ Dynamic Memory Control And Debug Library
💻 C
📖 第 1 页 / 共 5 页
字号:

static void   *(*xmem_malloc_ptr)(size_t DBG_PARAMS_PROTO) = NULL;
static void   *(*xmem_calloc_ptr)(size_t, size_t DBG_PARAMS_PROTO) = NULL;
static void   *(*xmem_realloc_ptr)(void *, size_t DBG_PARAMS_PROTO) = NULL;
static void   *(*xmem_expand_ptr)(void *, size_t DBG_PARAMS_PROTO) = NULL;
static void    (*xmem_free_ptr)(void * DBG_PARAMS_PROTO) = NULL;
static char   *(*xmem_strdup_ptr)(const char *) = NULL;

#define XMEM_MALLOC__(s)    xmem_malloc_ptr(s DBG_PARAMS)
#define XMEM_CALLOC__(c,s)  xmem_calloc_ptr(c,s DBG_PARAMS)
#define XMEM_REALLOC__(p,s) xmem_realloc_ptr(p,s DBG_PARAMS)
#define XMEM_EXPAND__(p,s)  xmem_expand_ptr(p,s DBG_PARAMS)
#define XMEM_FREE__(p)      xmem_free_ptr(p DBG_PARAMS)
#define XMEM_STRDUP__       xmem_strdup_ptr

#else                   /* XMEM_ALLOC_LIB */

#define XMEM_MALLOC__       malloc
#define XMEM_CALLOC__       calloc
#define XMEM_REALLOC__      realloc
#define XMEM_EXPAND__       _expand
#define XMEM_FREE__         free
#define XMEM_STRDUP__       strdup

#endif                  /* XMEM_ALLOC_LIB */

/*****************************************************************************/
/*****************************************************************************/
/* multi threading */
/*****************************************************************************/
/*****************************************************************************/
#if XMEM_THREAD
 static HANDLE xmem_hSem = NULL;
 #define XMEM_THREAD_ENTER_CRITICAL_SECTION() { if (xmem_hSem == NULL)                                    \
                                                { xmem_hSem = CreateMutex(NULL, TRUE, (PTR2STR)"XMEM"); } \
                                                else                                                      \
                                                { WaitForSingleObject(xmem_hSem, INFINITE); }             \
                                              }
 #define XMEM_THREAD_LEAVE_CRITICAL_SECTION() ReleaseMutex(xmem_hSem)
#else
 #define XMEM_THREAD_ENTER_CRITICAL_SECTION()
 #define XMEM_THREAD_LEAVE_CRITICAL_SECTION()
#endif

/*****************************************************************************/
/*****************************************************************************/
/* call stack tracing */
/*****************************************************************************/
/*****************************************************************************/
#if XMEM_CALLSTACK                      /* XMEM_CALLSTACK */

#define CALLS_LIMIT_INITIAL     40      /* initial number of calls between hash optimization */
#define CALLS_LIMIT             100000  /* upper limit of calls for hash optimization */

struct _s_names                 /* used to store names */
{
  struct _s_names  *next;       /* pointer to next element */
  SGN08            *name;       /* pointer to name */
};
typedef struct _s_names S_NAMES;

static S_NAMES *xmem_name_hashtable[XMEM_HASHSIZE]; /* hashtable for names */

static UNS16    xmem_string_hashfunc(SGN08 *);
static SGN08   *xmem_add_name(SGN08 *);
static S_NAMES *xmem_append_name(SGN08 *, S_NAMES *);
static S_NAMES *xmem_search_name(SGN08 *, S_NAMES *);
static void     xmem_deinit_names(void);

struct _s_callstack_hash_entry  /* one call stack frame hash entry */
{
  S_CALLSTACK_ENTRY               entry;            /* stack entry element */
#if XMEM_CALLSTACK_HASH
  UNS32                           hits;             /* number of hits */
#endif
  struct _s_callstack_hash_entry *next;             /* next stack entry */
};
typedef struct _s_callstack_hash_entry  S_CALLSTACK_HASH_ENTRY;

static S_CALLSTACK  g_cstk;     /* local static object used for call stack handling */

/**** derived XMEM_StackWalker class ****/
class XMEM_StackWalker : public StackWalker
{
public:
  int m_entry_index;                /* index for call stack frame */
#if XMEM_CALLSTACK_HASH
  UNS32 m_calls;
  UNS32 m_calls_limit;
#endif
  static S_CALLSTACK *m_pcstk;      /* pointer to call stack structure */
  static S_CALLSTACK_HASH_ENTRY *m_phashroot;   /* pointer to call stack hash */
  static UNS32 m_hashcnt;
  static SGN32 m_stack_depth_warning;

  /**** constructor ****/
  XMEM_StackWalker() : StackWalker()
  {
#if XMEM_CALLSTACK_HASH
    m_calls = 0;
    m_calls_limit = CALLS_LIMIT_INITIAL;
#endif
  };
  /**** constructor ****/
  XMEM_StackWalker(DWORD dwProcessId, HANDLE hProcess) : StackWalker(dwProcessId, hProcess) {};
  /**** destructor ****/
  virtual ~XMEM_StackWalker()
  {
    S_CALLSTACK_HASH_ENTRY *pentry, *pentry_next;
    for (pentry = m_phashroot; pentry != NULL; pentry = pentry_next)
    { /* free address entry element */
      pentry_next = pentry->next;
      XMEM_CALL_INTERNAL_LOCK();
      XMEM_FREE__(pentry);
      XMEM_CALL_INTERNAL_UNLOCK();
    }
    m_phashroot = NULL;
    m_hashcnt = 0;
  };
  /**** process and add one callstack entry ****/
  virtual void OnCallstackEntry(CallstackEntryType eType, CallstackEntry &entry)
  {
    CHAR buffer[STACKWALK_MAX_NAMELEN];
    if ((eType != lastEntry) && (entry.offset != 0))
    {
      if (m_entry_index < MAX_CALLSTACK)
      { /* one valid callstack entry within logging index limit */
        if (m_pentry == NULL)     /* is address already known? */
        {
          /* get the function name */
          if (entry.undFullName[0] != 0)
            m_pcstk->entry[m_entry_index].funcname = xmem_add_name(entry.undFullName);
          else if (entry.undName[0] != 0)
            m_pcstk->entry[m_entry_index].funcname = xmem_add_name(entry.undName);
          else
            m_pcstk->entry[m_entry_index].funcname = xmem_add_name("(function-name not available)");
          /* get the filename */
          if (entry.lineFileName[0] == 0)
          {
            _snprintf_s(buffer, STACKWALK_MAX_NAMELEN, "0x%p (%s): %s", (LPVOID)entry.offset,
                                                                        (entry.moduleName[0] == 0) ? "(module-name not available)"
                                                                                                   : entry.moduleName,
                                                                        "(filename not available)"
                       );
            m_pcstk->entry[m_entry_index].filename = xmem_add_name(buffer);
          }
          else
          {
            m_pcstk->entry[m_entry_index].filename = xmem_add_name(entry.lineFileName);
          }
          m_pcstk->entry[m_entry_index].lineno = (UNS32)entry.lineNumber; /* get the line number */
          m_pcstk->entry[m_entry_index].offset = entry.offset;            /* address offset */
          add_entry(entry.offset, &m_pcstk->entry[m_entry_index]);    /* remember address entry element */
        }
        else
        { /* address entry is knwon, simply copy it */
          m_pcstk->entry[m_entry_index] = ((S_CALLSTACK_HASH_ENTRY *)m_pentry)->entry;
        }
      }
      else
      { /* maximum call stack depth exceeded */
        if (m_entry_index > m_stack_depth_warning)
        {
          xmem_printf("\nREMARK: XMEM internal maximum trace call stack depth exceeded (%ld > %ld)",
                      (SGN32)m_entry_index,
                      (SGN32)MAX_CALLSTACK
                     );
          m_stack_depth_warning = m_entry_index;
        }
      }
    }
    ++m_entry_index;        /* increment logging index */
  };
  virtual void OnDbgHelpErr(LPCSTR /* szFuncName */, DWORD /* gle */, DWORD64 /* addr */) { };
  virtual void OnOutput(LPCSTR /* szText */) { };
  virtual void OnOutput(LPCWSTR /* szText */) { };
  /**** initialize callstack displaying ****/
  void init_ShowCallstack(void)
  {
    m_entry_index = 0;                          /* init the stack frame index */
    if (m_pcstk)
    {
      memset(m_pcstk, 0, sizeof(S_CALLSTACK));  /* initialize the call stack frame structure */
    }
  };
  /**** search callstack entry ****/
  void *search_entry(DWORD64 offset)
  { /* search if address is already known */
    S_CALLSTACK_HASH_ENTRY *pentry;
    for (pentry = m_phashroot; pentry != NULL; pentry = pentry->next)
    {
      if (pentry->entry.offset == offset)
      { /* entry found, leave for loop */
#if XMEM_CALLSTACK_HASH
        ++pentry->hits;
#endif
        goto LBL_END;
      }
    }
LBL_END:
#if XMEM_CALLSTACK_HASH
    if (++m_calls > m_calls_limit)
    { /* limit reached, reorganize hash list to optimize access */
      S_CALLSTACK_HASH_ENTRY *pentry1, *pentry2, *pentry_tmp;
      S_CALLSTACK_ENTRY       tmp_entry;
      UNS32                   tmp_hits;
      UNS08                   is_reorganized = FALSE;
      for (pentry1 = m_phashroot; pentry1 != NULL; pentry1 = pentry1->next)
      { /* sort hash list entries in descending hit order */
        pentry_tmp = NULL;
        for (pentry2 = pentry1->next; pentry2 != NULL; pentry2 = pentry2->next)
        { /* find largest hit value in remaining list */
          if (   (   (pentry_tmp == NULL)
                  && (pentry2->hits > pentry1->hits)
                 )
              || (   (pentry_tmp != NULL)
                  && (pentry2->hits > pentry_tmp->hits)
                 )
             )
          {
            pentry_tmp = pentry2;   /* remember entry */
          }
        }
        if (   (pentry_tmp != NULL)
            && (pentry_tmp != pentry1)
           )
        { /* new largest hit value found, exchange entries in place */
          tmp_entry                  = pentry_tmp->entry;
          tmp_hits                   = pentry_tmp->hits;
          pentry_tmp->entry          = pentry1->entry;
          pentry_tmp->hits           = pentry1->hits;
          pentry1->entry             = tmp_entry;
          pentry1->hits              = tmp_hits;
          if (pentry1->entry.offset == offset)
          {
            pentry = pentry1;
          }
          is_reorganized = TRUE;    /* remember that exchange took place */
        }
      }
      m_calls = 0;                  /* reset value */
      if (is_reorganized == FALSE)
      { /* no reorganization, increase limit */
        if (m_calls_limit < CALLS_LIMIT)
        {                       /* since calls limit is not reached  */
          m_calls_limit *= 2;   /* multiply limit with factor 2 */
        }
      }
    }
#endif
    return(pentry);
  }
  /**** add callstack entry ****/
  S_CALLSTACK_HASH_ENTRY *add_entry(DWORD64 offset, S_CALLSTACK_ENTRY *entry)
  { /* add address entry element */
    S_CALLSTACK_HASH_ENTRY *pentry, *plastentry = NULL;
    if (m_phashroot == NULL)
    { /* no list element present, make first entry */
      XMEM_CALL_INTERNAL_LOCK();
      pentry = (S_CALLSTACK_HASH_ENTRY *)XMEM_CALLOC__(1,
                                                       sizeof(S_CALLSTACK_HASH_ENTRY)
                                                      );
      XMEM_CALL_INTERNAL_UNLOCK();
      m_phashroot = pentry;
    }
    else
    { /* search linked list for entry */
      for (pentry = m_phashroot; pentry != NULL; pentry = pentry->next)
      {
        if (pentry->entry.offset == offset)
        {
          return(pentry);       /* identical entry already in list */
        }
        plastentry = pentry;
      }
      XMEM_CALL_INTERNAL_LOCK();
      pentry = (S_CALLSTACK_HASH_ENTRY *)XMEM_CALLOC__(1,
                                                       sizeof(S_CALLSTACK_HASH_ENTRY)
                                                      );
      XMEM_CALL_INTERNAL_UNLOCK();
      plastentry->next = pentry;
    }
    pentry->entry = *entry;             /* copy complete address element */
    pentry->entry.offset = offset;      /* remember address */
    ++m_hashcnt;                        /* increment hash entry counter */
    return(pentry);
  }
};
S_CALLSTACK *XMEM_StackWalker::m_pcstk = &g_cstk;   /* set static class pointer to call stack frame structure object */
S_CALLSTACK_HASH_ENTRY *XMEM_StackWalker::m_phashroot = NULL;   /* initialize hash pointer */
UNS32 XMEM_StackWalker::m_hashcnt = 0;
SGN32 XMEM_StackWalker::m_stack_depth_warning = MAX_CALLSTACK;

static XMEM_StackWalker sw;                     /* create one callstack instance */
static BOOLEAN cstck_flag = FALSE;

#define GET_XMEM_CALLSTACK()        { if (cstck_flag == FALSE) { cstck_flag = TRUE; sw.init_ShowCallstack(); sw.ShowCallstack(); cstck_flag = FALSE; } }
static void xmem_show_callstack(S_CALLSTACK *p_cstk);
#define XMEM_SHOW_CALLSTACK(x)      { if (cstck_flag == FALSE) { cstck_flag = TRUE; xmem_show_callstack(x); cstck_flag = FALSE; } }

#else                                   /* XMEM_CALLSTACK */
#define GET_XMEM_CALLSTACK()
#define XMEM_SHOW_CALLSTACK(x)
#endif                                  /* XMEM_CALLSTACK */

/*****************************************************************************/
/*****************************************************************************/
/* XMEM settings, displayed during compilation and written to error logfile  */
/*****************************************************************************/
/*****************************************************************************/
void xmem_settings(FILE *fptr)
{
#if XMEM_SETTINGS
  fprintf(fptr, "\n******** XMEM settings ********\n");
#if XMEM
#pragma message("XMEM enabled")
  fprintf(fptr, "XMEM enabled\n");
#else
#pragma message("XMEM disabled")
  fprintf(fptr, "XMEM disabled\n");
#endif
#if XMEM_CPP
#pragma message("XMEM_CPP enabled")
  fprintf(fptr, "XMEM_CPP enabled\n");
#else
#pragma message("XMEM_CPP disabled")
  fprintf(fptr, "XMEM_CPP disabled\n");
#endif
#if XMEM_CRITICAL_OPERATOR
#pragma message("XMEM_CRITICAL_OPERATOR enabled")
  fprintf(fptr, "XMEM_CRITICAL_OPERATOR enabled\n");
#else
#pragma message("XMEM_CRITICAL_OPERATOR disabled")
  fprintf(fptr, "XMEM_CRITICAL_OPERATOR disabled\n");
#endif
#if XMEM_NEWARRAY
#pragma message("XMEM_NEWARRAY enabled")
  fprintf(fptr, "XMEM_NEWARRAY enabled\n");
#else
#pragma message("XMEM_NEWARRAY disabled")
  fprintf(fptr, "XMEM_NEWARRAY disabled\n");
#endif
#if XMEM_DELETEARRAY
#pragma message("XMEM_DELETEARRAY enabled")
  fprintf(fptr, "XMEM_DELETEARRAY enabled\n");
#else
#pragma message("XMEM_DELETEARRAY disabled")
  fprintf(fptr, "XMEM_DELETEARRAY disabled\n");
#endif
#if XMEM_CPP_DELETE_STACK
#pragma message("XMEM_CPP_DELETE_STACK enabled")
  fprintf(fptr, "XMEM_CPP_DELETE_STACK enabled\n");

⌨️ 快捷键说明

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