memory.cpp

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

CPP
1,171
字号

        if (info->GetBaseClassName1() && !info->GetBaseClassName2())
        {
            msg += wxT("is a ");
            msg += info->GetBaseClassName1();
        }
        else if (info->GetBaseClassName1() && info->GetBaseClassName2())
        {
            msg += wxT("is a ");
            msg += info->GetBaseClassName1() ;
            msg += wxT(", ");
            msg += info->GetBaseClassName2() ;
        }
        if (info->GetConstructor())
            msg += wxT(": dynamic");

        wxLogMessage(msg);
    }
    node = wxClassInfo::sm_classTable->Next();
    n ++;
  }
  wxLogMessage(wxEmptyString);
  wxLogMessage(wxT("There are %d classes derived from wxObject."), n);
  wxLogMessage(wxEmptyString);
  wxLogMessage(wxEmptyString);
  return true;
}

void wxDebugContext::SetCheckpoint(bool all)
{
  if (all)
    checkPoint = NULL;
  else
    checkPoint = m_tail;
}

// Checks all nodes since checkpoint, or since start.
int wxDebugContext::Check(bool checkAll)
{
  int nFailures = 0;

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

  for (wxMemStruct * st = from; st != 0; st = st->m_next)
  {
    if (st->AssertIt ())
      nFailures += st->CheckBlock ();
    else
      return -1;
  }

  return nFailures;
}

// Count the number of non-wxDebugContext-related objects
// that are outstanding
int wxDebugContext::CountObjectsLeft(bool sinceCheckpoint)
{
  int n = 0;

  wxMemStruct *from = NULL;
  if (sinceCheckpoint && checkPoint)
    from = checkPoint->m_next;
  else
    from = wxDebugContext::GetHead () ;

  for (wxMemStruct * st = from; st != 0; st = st->m_next)
  {
      void* data = st->GetActualData();
      if (data != (void*) wxLog::GetActiveTarget())
          n ++;
  }

  return n ;
}

// This function is used to output the dump
void wxDebugContext::OutputDumpLine(const wxChar *szFormat, ...)
{
    // a buffer of 2048 bytes should be long enough for a file name
    // and a class name
    wxChar buf[2048];
    int count;
    va_list argptr;
    va_start(argptr, szFormat);
    buf[sizeof(buf)/sizeof(wxChar)-1] = _T('\0');

    // keep 3 bytes for a \r\n\0
    count = wxVsnprintf(buf, sizeof(buf)/sizeof(wxChar)-3, szFormat, argptr);

    if ( count < 0 )
        count = sizeof(buf)/sizeof(wxChar)-3;
    buf[count]=_T('\r');
    buf[count+1]=_T('\n');
    buf[count+2]=_T('\0');

    wxMessageOutputDebug dbgout;
    dbgout.Printf(buf);
}


#if USE_THREADSAFE_MEMORY_ALLOCATION
static bool memSectionOk = false;

class MemoryCriticalSection : public wxCriticalSection
{
public:
    MemoryCriticalSection() {
        memSectionOk = true;
    }
    ~MemoryCriticalSection() {
        memSectionOk = false;
    }
};

class MemoryCriticalSectionLocker
{
public:
    inline MemoryCriticalSectionLocker(wxCriticalSection& critsect)
    : m_critsect(critsect), m_locked(memSectionOk) { if(m_locked) m_critsect.Enter(); }
    inline ~MemoryCriticalSectionLocker() { if(m_locked) m_critsect.Leave(); }

private:
    // no assignment operator nor copy ctor
    MemoryCriticalSectionLocker(const MemoryCriticalSectionLocker&);
    MemoryCriticalSectionLocker& operator=(const MemoryCriticalSectionLocker&);

    wxCriticalSection& m_critsect;
    bool m_locked;
};

static MemoryCriticalSection memLocker;

#endif

#if !(defined(__WXMSW__) && (defined(WXUSINGDLL) || defined(WXMAKINGDLL_BASE)))
#ifdef __WXDEBUG__
#if wxUSE_GLOBAL_MEMORY_OPERATORS
void * operator new (size_t size, wxChar * fileName, int lineNum)
{
    return wxDebugAlloc(size, fileName, lineNum, false, false);
}

void * operator new (size_t size)
{
    return wxDebugAlloc(size, NULL, 0, false);
}

void operator delete (void * buf)
{
    wxDebugFree(buf, false);
}

#if wxUSE_ARRAY_MEMORY_OPERATORS
void * operator new[] (size_t size)
{
    return wxDebugAlloc(size, NULL, 0, false, true);
}

void * operator new[] (size_t size, wxChar * fileName, int lineNum)
{
    return wxDebugAlloc(size, fileName, lineNum, false, true);
}

void operator delete[] (void * buf)
{
  wxDebugFree(buf, true);
}
#endif // wxUSE_ARRAY_MEMORY_OPERATORS
#endif // !(defined(__WXMSW__) && (defined(WXUSINGDLL) || defined(WXMAKINGDLL_BASE)))
#endif // wxUSE_GLOBAL_MEMORY_OPERATORS

// TODO: store whether this is a vector or not.
void * wxDebugAlloc(size_t size, wxChar * fileName, int lineNum, bool isObject, bool WXUNUSED(isVect) )
{
#if USE_THREADSAFE_MEMORY_ALLOCATION
  MemoryCriticalSectionLocker lock(memLocker);
#endif

  // If not in debugging allocation mode, do the normal thing
  // so we don't leave any trace of ourselves in the node list.

#if defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 )
// VA 3.0 still has trouble in here
  return (void *)malloc(size);
#endif
  if (!wxDebugContext::GetDebugMode())
  {
    return (void *)malloc(size);
  }

    int totSize = wxDebugContext::TotSize (size);
    char * buf = (char *) malloc(totSize);
    if (!buf) {
        wxLogMessage(wxT("Call to malloc (%ld) failed."), (long)size);
        return 0;
    }
    wxMemStruct * st = (wxMemStruct *)buf;
    st->m_firstMarker = MemStartCheck;
    st->m_reqSize = size;
    st->m_fileName = fileName;
    st->m_lineNum = lineNum;
    st->m_id = MemStructId;
    st->m_prev = 0;
    st->m_next = 0;
    st->m_isObject = isObject;

    // Errors from Append() shouldn't really happen - but just in case!
    if (st->Append () == 0) {
        st->ErrorMsg ("Trying to append new node");
    }

    if (wxDebugContext::GetCheckPrevious ()) {
        if (st->CheckAllPrevious () < 0) {
            st->ErrorMsg ("Checking previous nodes");
        }
    }

    // Set up the extra markers at the middle and end.
    char * ptr = wxDebugContext::MidMarkerPos (buf);
    * (wxMarkerType *) ptr = MemMidCheck;
    ptr = wxDebugContext::EndMarkerPos (buf, size);
    * (wxMarkerType *) ptr = MemEndCheck;

    // pointer returned points to the start of the caller's
    // usable area.
    void *m_actualData = (void *) wxDebugContext::CallerMemPos (buf);
    st->m_actualData = m_actualData;

    return m_actualData;
}

// TODO: check whether was allocated as a vector
void wxDebugFree(void * buf, bool WXUNUSED(isVect) )
{
#if USE_THREADSAFE_MEMORY_ALLOCATION
  MemoryCriticalSectionLocker lock(memLocker);
#endif

  if (!buf)
    return;

#if defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 )
// VA 3.0 still has trouble in here
  free((char *)buf);
#endif
  // If not in debugging allocation mode, do the normal thing
  // so we don't leave any trace of ourselves in the node list.
  if (!wxDebugContext::GetDebugMode())
  {
    free((char *)buf);
    return;
  }

    // Points to the start of the entire allocated area.
    char * startPointer = wxDebugContext::StartPos ((char *) buf);
    // Find the struct and make sure that it's identifiable.
    wxMemStruct * st = (wxMemStruct *) wxDebugContext::StructPos (startPointer);

    if (! st->ValidateNode ())
        return;

    // If this is the current checkpoint, we need to
    // move the checkpoint back so it points to a valid
    // node.
    if (st == wxDebugContext::checkPoint)
      wxDebugContext::checkPoint = wxDebugContext::checkPoint->m_prev;

    if (! st->Unlink ())
    {
      st->ErrorMsg ("Unlinking deleted node");
    }

    // Now put in the fill char into the id slot and the caller requested
    // memory locations.
    st->SetDeleted ();
    (void) memset (wxDebugContext::CallerMemPos (startPointer), MemFillChar,
                   st->RequestSize ());

    free((char *)st);
}

#endif // __WXDEBUG__

// Trace: send output to the current debugging stream
void wxTrace(const wxChar * ...)
{
#if 1
    wxFAIL_MSG(wxT("wxTrace is now obsolete. Please use wxDebugXXX instead."));
#else
    va_list ap;
  static wxChar buffer[512];

  va_start(ap, fmt);

#ifdef __WXMSW__
  wvsprintf(buffer,fmt,ap) ;
#else
  vsprintf(buffer,fmt,ap) ;
#endif

  va_end(ap);

  if (wxDebugContext::HasStream())
  {
    wxDebugContext::GetStream() << buffer;
    wxDebugContext::GetStream().flush();
  }
  else
#ifdef __WXMSW__
#ifdef __WIN32__
    OutputDebugString((LPCTSTR)buffer) ;
#else
    OutputDebugString((const char*) buffer) ;
#endif
#else
    fprintf(stderr, buffer);
#endif
#endif
}

// Trace with level
void wxTraceLevel(int, const wxChar * ...)
{
#if 1
    wxFAIL_MSG(wxT("wxTrace is now obsolete. Please use wxDebugXXX instead."));
#else
  if (wxDebugContext::GetLevel() < level)
    return;

  va_list ap;
  static wxChar buffer[512];

  va_start(ap, fmt);

#ifdef __WXMSW__
  wxWvsprintf(buffer,fmt,ap) ;
#else
  vsprintf(buffer,fmt,ap) ;
#endif

  va_end(ap);

  if (wxDebugContext::HasStream())
  {
    wxDebugContext::GetStream() << buffer;
    wxDebugContext::GetStream().flush();
  }
  else
#ifdef __WXMSW__
#ifdef __WIN32__
    OutputDebugString((LPCTSTR)buffer) ;
#else
    OutputDebugString((const char*) buffer) ;
#endif
#else
    fprintf(stderr, buffer);
#endif
#endif
}

//----------------------------------------------------------------------------
// Final cleanup after all global objects in all files have been destroyed
//----------------------------------------------------------------------------

// Don't set it to 0 by dynamic initialization
// Some compilers will really do the assignment later
// All global variables are initialized to 0 at the very beginning, and this is just fine.
int wxDebugContextDumpDelayCounter::sm_count;

void wxDebugContextDumpDelayCounter::DoDump()
{
    if (wxDebugContext::CountObjectsLeft(true) > 0)
    {
        wxDebugContext::OutputDumpLine(wxT("There were memory leaks.\n"));
        wxDebugContext::Dump();
        wxDebugContext::PrintStatistics();
    }
}

// Even if there is nothing else, make sure that there is at
// least one cleanup counter object
static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_One;

#endif // (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT

⌨️ 快捷键说明

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