memory.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,171 行 · 第 1/3 页

CPP
1,171
字号
    msg2.Printf(wxT(" at 0x%lX, size %d"), (long)GetActualData(), (int)RequestSize());
    msg += msg2;

    wxDebugContext::OutputDumpLine(msg);
  }
  else
  {
    wxString msg;
    if (m_fileName)
      msg.Printf(wxT("%s(%d): "), m_fileName, (int)m_lineNum);

    wxString msg2;
    msg2.Printf(wxT("non-object data at 0x%lX, size %d"), (long)GetActualData(), (int)RequestSize() );
    msg += msg2;
    wxDebugContext::OutputDumpLine(msg);
  }
}


/*
  Validate a node. Check to see that the node is "clean" in the sense
  that nothing has over/underwritten it etc.
*/
int wxMemStruct::ValidateNode ()
{
    char * startPointer = (char *) this;
    if (!AssertIt ()) {
        if (IsDeleted ())
            ErrorMsg ("Object already deleted");
        else {
            // Can't use the error routines as we have no recognisable object.
#ifndef __WXGTK__
             wxLogMessage(wxT("Can't verify memory struct - all bets are off!"));
#endif
        }
        return 0;
    }

/*
    int i;
    for (i = 0; i < wxDebugContext::TotSize (requestSize ()); i++)
      cout << startPointer [i];
    cout << endl;
*/
    if (Marker () != MemStartCheck)
      ErrorMsg ();
    if (* (wxMarkerType *) wxDebugContext::MidMarkerPos (startPointer) != MemMidCheck)
      ErrorMsg ();
    if (* (wxMarkerType *) wxDebugContext::EndMarkerPos (startPointer,
                                              RequestSize ()) !=
        MemEndCheck)
      ErrorMsg ();

    // Back to before the extra buffer and check that
    // we can still read what we originally wrote.
    if (Marker () != MemStartCheck ||
        * (wxMarkerType *) wxDebugContext::MidMarkerPos (startPointer)
                         != MemMidCheck ||
        * (wxMarkerType *) wxDebugContext::EndMarkerPos (startPointer,
                                              RequestSize ()) != MemEndCheck)
    {
        ErrorMsg ();
        return 0;
    }

    return 1;
}

/*
  The wxDebugContext class.
*/

wxMemStruct *wxDebugContext::m_head = NULL;
wxMemStruct *wxDebugContext::m_tail = NULL;

bool wxDebugContext::m_checkPrevious = false;
int wxDebugContext::debugLevel = 1;
bool wxDebugContext::debugOn = true;
wxMemStruct *wxDebugContext::checkPoint = NULL;

// For faster alignment calculation
static wxMarkerType markerCalc[2];
int wxDebugContext::m_balign = (int)((char *)&markerCalc[1] - (char*)&markerCalc[0]);
int wxDebugContext::m_balignmask = (int)((char *)&markerCalc[1] - (char*)&markerCalc[0]) - 1;

wxDebugContext::wxDebugContext(void)
{
}

wxDebugContext::~wxDebugContext(void)
{
}

/*
  Work out the positions of the markers by creating an array of 2 markers
  and comparing the addresses of the 2 elements. Use this number as the
  alignment for markers.
*/
size_t wxDebugContext::CalcAlignment ()
{
    wxMarkerType ar[2];
    return (char *) &ar[1] - (char *) &ar[0];
}


char * wxDebugContext::StructPos (const char * buf)
{
    return (char *) buf;
}

char * wxDebugContext::MidMarkerPos (const char * buf)
{
    return StructPos (buf) + PaddedSize (sizeof (wxMemStruct));
}

char * wxDebugContext::CallerMemPos (const char * buf)
{
    return MidMarkerPos (buf) + PaddedSize (sizeof(wxMarkerType));
}


char * wxDebugContext::EndMarkerPos (const char * buf, const size_t size)
{
    return CallerMemPos (buf) + PaddedSize (size);
}


/*
  Slightly different as this takes a pointer to the start of the caller
  requested region and returns a pointer to the start of the buffer.
  */
char * wxDebugContext::StartPos (const char * caller)
{
    return ((char *) (caller - wxDebugContext::PaddedSize (sizeof(wxMarkerType)) -
            wxDebugContext::PaddedSize (sizeof (wxMemStruct))));
}

/*
  We may need padding between various parts of the allocated memory.
  Given a size of memory, this returns the amount of memory which should
  be allocated in order to allow for alignment of the following object.

  I don't know how portable this stuff is, but it seems to work for me at
  the moment. It would be real nice if I knew more about this!

  // Note: this function is now obsolete (along with CalcAlignment)
  // because the calculations are done statically, for greater speed.
*/
size_t wxDebugContext::GetPadding (const size_t size)
{
    size_t pad = size % CalcAlignment ();
    return (pad) ? sizeof(wxMarkerType) - pad : 0;
}

size_t wxDebugContext::PaddedSize (const size_t size)
{
    // Added by Terry Farnham <TJRT@pacbell.net> to replace
    // slow GetPadding call.
    int padb;

    padb = size & m_balignmask;
    if(padb)
        return(size + m_balign - padb);
    else
        return(size);
}

/*
  Returns the total amount of memory which we need to get from the system
  in order to satisfy a caller request. This includes space for the struct
  plus markers and the caller's memory as well.
*/
size_t wxDebugContext::TotSize (const size_t reqSize)
{
    return (PaddedSize (sizeof (wxMemStruct)) + PaddedSize (reqSize) +
            2 * sizeof(wxMarkerType));
}


/*
  Traverse the list of nodes executing the given function on each node.
*/
void wxDebugContext::TraverseList (PmSFV func, wxMemStruct *from)
{
  if (!from)
    from = wxDebugContext::GetHead ();

  wxMemStruct * st = NULL;
  for (st = from; st != 0; st = st->m_next)
  {
      void* data = st->GetActualData();
//      if ((data != (void*)m_debugStream) && (data != (void*) m_streamBuf))
      if (data != (void*) wxLog::GetActiveTarget())
      {
        (st->*func) ();
      }
  }
}


/*
  Print out the list.
  */
bool wxDebugContext::PrintList (void)
{
#ifdef __WXDEBUG__
  TraverseList ((PmSFV)&wxMemStruct::PrintNode, (checkPoint ? checkPoint->m_next : (wxMemStruct*)NULL));

  return true;
#else
  return false;
#endif
}

bool wxDebugContext::Dump(void)
{
#ifdef __WXDEBUG__
  {
    wxChar* appName = (wxChar*) wxT("application");
    wxString appNameStr;
    if (wxTheApp)
    {
        appNameStr = wxTheApp->GetAppName();
        appName = WXSTRINGCAST appNameStr;
        OutputDumpLine(wxT("----- Memory dump of %s at %s -----"), appName, WXSTRINGCAST wxNow() );
    }
    else
    {
      OutputDumpLine( wxT("----- Memory dump -----") );
    }
  }

  TraverseList ((PmSFV)&wxMemStruct::Dump, (checkPoint ? checkPoint->m_next : (wxMemStruct*)NULL));

  OutputDumpLine(wxEmptyString);
  OutputDumpLine(wxEmptyString);

  return true;
#else
  return false;
#endif
}

#ifdef __WXDEBUG__
struct wxDebugStatsStruct
{
  long instanceCount;
  long totalSize;
  wxChar *instanceClass;
  wxDebugStatsStruct *next;
};

static wxDebugStatsStruct *FindStatsStruct(wxDebugStatsStruct *st, wxChar *name)
{
  while (st)
  {
    if (wxStrcmp(st->instanceClass, name) == 0)
      return st;
    st = st->next;
  }
  return NULL;
}

static wxDebugStatsStruct *InsertStatsStruct(wxDebugStatsStruct *head, wxDebugStatsStruct *st)
{
  st->next = head;
  return st;
}
#endif

bool wxDebugContext::PrintStatistics(bool detailed)
{
#ifdef __WXDEBUG__
  {
    wxChar* appName = (wxChar*) wxT("application");
    wxString appNameStr;
    if (wxTheApp)
    {
        appNameStr = wxTheApp->GetAppName();
        appName = WXSTRINGCAST appNameStr;
        OutputDumpLine(wxT("----- Memory statistics of %s at %s -----"), appName, WXSTRINGCAST wxNow() );
    }
    else
    {
      OutputDumpLine( wxT("----- Memory statistics -----") );
    }
  }

  bool currentMode = GetDebugMode();
  SetDebugMode(false);

  long noNonObjectNodes = 0;
  long noObjectNodes = 0;
  long totalSize = 0;

  wxDebugStatsStruct *list = NULL;

  wxMemStruct *from = (checkPoint ? checkPoint->m_next : (wxMemStruct*)NULL );
  if (!from)
    from = wxDebugContext::GetHead ();

  wxMemStruct *st;
  for (st = from; st != 0; st = st->m_next)
  {
    void* data = st->GetActualData();
    if (detailed && (data != (void*) wxLog::GetActiveTarget()))
    {
      wxChar *className = (wxChar*) wxT("nonobject");
      if (st->m_isObject && st->GetActualData())
      {
        wxObject *obj = (wxObject *)st->GetActualData();
        if (obj->GetClassInfo()->GetClassName())
          className = (wxChar*)obj->GetClassInfo()->GetClassName();
      }
      wxDebugStatsStruct *stats = FindStatsStruct(list, className);
      if (!stats)
      {
        stats = (wxDebugStatsStruct *)malloc(sizeof(wxDebugStatsStruct));
        stats->instanceClass = className;
        stats->instanceCount = 0;
        stats->totalSize = 0;
        list = InsertStatsStruct(list, stats);
      }
      stats->instanceCount ++;
      stats->totalSize += st->RequestSize();
    }

    if (data != (void*) wxLog::GetActiveTarget())
    {
        totalSize += st->RequestSize();
        if (st->m_isObject)
            noObjectNodes ++;
        else
            noNonObjectNodes ++;
    }
  }

  if (detailed)
  {
    while (list)
    {
      OutputDumpLine(wxT("%ld objects of class %s, total size %ld"),
          list->instanceCount, list->instanceClass, list->totalSize);
      wxDebugStatsStruct *old = list;
      list = old->next;
      free((char *)old);
    }
    OutputDumpLine(wxEmptyString);
  }

  SetDebugMode(currentMode);

  OutputDumpLine(wxT("Number of object items: %ld"), noObjectNodes);
  OutputDumpLine(wxT("Number of non-object items: %ld"), noNonObjectNodes);
  OutputDumpLine(wxT("Total allocated size: %ld"), totalSize);
  OutputDumpLine(wxEmptyString);
  OutputDumpLine(wxEmptyString);

  return true;
#else
  (void)detailed;
  return false;
#endif
}

bool wxDebugContext::PrintClasses(void)
{
  {
    wxChar* appName = (wxChar*) wxT("application");
    wxString appNameStr;
    if (wxTheApp)
    {
        appNameStr = wxTheApp->GetAppName();
        appName = WXSTRINGCAST appNameStr;
        wxLogMessage(wxT("----- Classes in %s -----"), appName);
    }
  }

  int n = 0;
  wxHashTable::compatibility_iterator node;
  wxClassInfo *info;

  wxClassInfo::sm_classTable->BeginFind();
  node = wxClassInfo::sm_classTable->Next();
  while (node)
  {
    info = (wxClassInfo *)node->GetData();
    if (info->GetClassName())
    {
        wxString msg(info->GetClassName());
        msg += wxT(" ");

⌨️ 快捷键说明

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