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 + -
显示快捷键?