]>
git.saurik.com Git - wxWidgets.git/blob - src/common/memory.cpp
5302fe214d5001cbe450a8589e79bf8ac60db193
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Memory checking implementation 
   4 // Author:      Arthur Seaton, Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation "memory.h" 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  27 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT 
  30 // #pragma implementation 
  41 #include "wx/ioswrap.h" 
  52 #if !defined(__WATCOMC__) && !(defined(__VMS__) && ( __VMS_VER < 70000000 ) )\ 
  53      && !defined( __MWERKS__ ) && !defined(__SALFORDC__) 
  73 #include "wx/memory.h" 
  79 // wxDebugContext wxTheDebugContext; 
  81   Redefine new and delete so that we can pick up situations where: 
  82         - we overwrite or underwrite areas of malloc'd memory. 
  83         - we use uninitialise variables 
  84   Only do this in debug mode. 
  86   We change new to get enough memory to allocate a struct, followed 
  87   by the caller's requested memory, followed by a tag. The struct 
  88   is used to create a doubly linked list of these areas and also 
  89   contains another tag. The tags are used to determine when the area 
  90   has been over/under written. 
  95   Values which are used to set the markers which will be tested for 
  96   under/over write. There are 3 of these, one in the struct, one 
  97   immediately after the struct but before the caller requested memory and 
  98   one immediately after the requested memory. 
 100 #define MemStartCheck  0x23A8 
 101 #define MemMidCheck  0xA328 
 102 #define MemEndCheck 0x8A32 
 103 #define MemFillChar 0xAF 
 104 #define MemStructId  0x666D 
 107   External interface for the wxMemStruct class. Others are 
 108   defined inline within the class def. Here we only need to be able 
 109   to add and delete nodes from the list and handle errors in some way. 
 113   Used for internal "this shouldn't happen" type of errors. 
 115 void wxMemStruct::ErrorMsg (const char * mesg
) 
 117   wxLogMessage(wxT("wxWindows memory checking error: %s"), mesg
); 
 120 //         << m_fileName << ' ' << m_lineNum << endl; 
 124   Used when we find an overwrite or an underwrite error. 
 126 void wxMemStruct::ErrorMsg () 
 128   wxLogMessage(wxT("wxWindows over/underwrite memory error:")); 
 131 //    cerr << m_fileName << ' ' << m_lineNum << endl; 
 136   We want to find out if pointers have been overwritten as soon as is 
 137   possible, so test everything before we dereference it. Of course it's still 
 138   quite possible that, if things have been overwritten, this function will 
 139   fall over, but the only way of dealing with that would cost too much in terms 
 142 int wxMemStruct::AssertList () 
 144     if (wxDebugContext::GetHead () != 0 && ! (wxDebugContext::GetHead ())->AssertIt () || 
 145         wxDebugContext::GetTail () != 0 && ! wxDebugContext::GetTail ()->AssertIt ()) { 
 146         ErrorMsg ("Head or tail pointers trashed"); 
 154   Check that the thing we're pointing to has the correct id for a wxMemStruct 
 155   object and also that it's previous and next pointers are pointing at objects 
 156   which have valid ids. 
 157   This is definitely not perfect since we could fall over just trying to access 
 158   any of the slots which we use here, but I think it's about the best that I 
 159   can do without doing something like taking all new wxMemStruct pointers and 
 160   comparing them against all known pointer within the list and then only 
 161   doing this sort of check _after_ you've found the pointer in the list. That 
 162   would be safer, but also much more time consuming. 
 164 int wxMemStruct::AssertIt () 
 166     return (m_id 
== MemStructId 
&& 
 167             (m_prev 
== 0 || m_prev
->m_id 
== MemStructId
) && 
 168             (m_next 
== 0 || m_next
->m_id 
== MemStructId
)); 
 173   Additions are always at the tail of the list. 
 174   Returns 0 on error, non-zero on success. 
 176 int wxMemStruct::Append () 
 181     if (wxDebugContext::GetHead () == 0) { 
 182         if (wxDebugContext::GetTail () != 0) { 
 183             ErrorMsg ("Null list should have a null tail pointer"); 
 186         (void) wxDebugContext::SetHead (this); 
 187         (void) wxDebugContext::SetTail (this); 
 189         wxDebugContext::GetTail ()->m_next 
= this; 
 190         this->m_prev 
= wxDebugContext::GetTail (); 
 191         (void) wxDebugContext::SetTail (this); 
 198   Don't actually free up anything here as the space which is used 
 199   by the node will be free'd up when the whole block is free'd. 
 200   Returns 0 on error, non-zero on success. 
 202 int wxMemStruct::Unlink () 
 207     if (wxDebugContext::GetHead () == 0 || wxDebugContext::GetTail () == 0) { 
 208         ErrorMsg ("Trying to remove node from empty list"); 
 212     // Handle the part of the list before this node. 
 214         if (this != wxDebugContext::GetHead ()) { 
 215             ErrorMsg ("No previous node for non-head node"); 
 218         (void) wxDebugContext::SetHead (m_next
); 
 220         if (! m_prev
->AssertIt ()) { 
 221             ErrorMsg ("Trashed previous pointer"); 
 225         if (m_prev
->m_next 
!= this) { 
 226             ErrorMsg ("List is inconsistent"); 
 229         m_prev
->m_next 
= m_next
; 
 232     // Handle the part of the list after this node. 
 234         if (this != wxDebugContext::GetTail ()) { 
 235             ErrorMsg ("No next node for non-tail node"); 
 238         (void) wxDebugContext::SetTail (m_prev
); 
 240         if (! m_next
->AssertIt ()) { 
 241             ErrorMsg ("Trashed next pointer"); 
 245         if (m_next
->m_prev 
!= this) { 
 246             ErrorMsg ("List is inconsistent"); 
 249         m_next
->m_prev 
= m_prev
; 
 258   Checks a node and block of memory to see that the markers are still 
 261 int wxMemStruct::CheckBlock () 
 265     if (m_firstMarker 
!= MemStartCheck
) { 
 270     char * pointer 
= wxDebugContext::MidMarkerPos ((char *) this); 
 271     if (* (wxMarkerType 
*) pointer 
!= MemMidCheck
) { 
 276     pointer 
= wxDebugContext::EndMarkerPos ((char *) this, RequestSize ()); 
 277     if (* (wxMarkerType 
*) pointer 
!= MemEndCheck
) { 
 287   Check the list of nodes to see if they are all ok. 
 289 int wxMemStruct::CheckAllPrevious () 
 293     for (wxMemStruct 
* st 
= this->m_prev
; st 
!= 0; st 
= st
->m_prev
) { 
 295             nFailures 
+= st
->CheckBlock (); 
 305   When we delete a node we set the id slot to a specific value and then test 
 306   against this to see if a nodes have been deleted previously. I don't 
 307   just set the entire memory to the fillChar because then I'd be overwriting 
 308   useful stuff like the vtbl which may be needed to output the error message 
 309   including the file name and line numbers. Without this info the whole point 
 310   of this class is lost! 
 312 void wxMemStruct::SetDeleted () 
 317 int wxMemStruct::IsDeleted () 
 319     return (m_id 
== MemFillChar
); 
 324   Print out a single node. There are many far better ways of doing this 
 325   but this will suffice for now. 
 327 void wxMemStruct::PrintNode () 
 331     wxObject 
*obj 
= (wxObject 
*)m_actualData
; 
 332     wxClassInfo 
*info 
= obj
->GetClassInfo(); 
 334     // Let's put this in standard form so IDEs can load the file at the appropriate 
 336     wxString 
msg(wxT("")); 
 339       msg
.Printf(wxT("%s(%d): "), m_fileName
, (int)m_lineNum
); 
 341     if (info 
&& info
->GetClassName()) 
 342       msg 
+= info
->GetClassName(); 
 344       msg 
+= wxT("object"); 
 347     msg2
.Printf(wxT(" at $%lX, size %d"), (long)GetActualData(), (int)RequestSize()); 
 357       msg
.Printf(wxT("%s(%d): "), m_fileName
, (int)m_lineNum
); 
 358     msg 
+= wxT("non-object data"); 
 360     msg2
.Printf(wxT(" at $%lX, size %d\n"), (long)GetActualData(), (int)RequestSize()); 
 367 void wxMemStruct::Dump () 
 369   if (!ValidateNode()) return; 
 373     wxObject 
*obj 
= (wxObject 
*)m_actualData
; 
 375     wxString 
msg(wxT("")); 
 377       msg
.Printf(wxT("%s(%d): "), m_fileName
, (int)m_lineNum
); 
 380     /* TODO: We no longer have a stream (using wxLogDebug) so we can't dump it. 
 381      * Instead, do what wxObject::Dump does. 
 382      * What should we do long-term, eliminate Dumping? Or specify 
 383      * that MyClass::Dump should use wxLogDebug? Ugh. 
 384     obj->Dump(wxDebugContext::GetStream()); 
 387     if (obj
->GetClassInfo() && obj
->GetClassInfo()->GetClassName()) 
 388       msg 
+= obj
->GetClassInfo()->GetClassName(); 
 390       msg 
+= wxT("unknown object class"); 
 393     msg2
.Printf(wxT(" at $%lX, size %d"), (long)GetActualData(), (int)RequestSize()); 
 400     wxString 
msg(wxT("")); 
 402       msg
.Printf(wxT("%s(%d): "), m_fileName
, (int)m_lineNum
); 
 405     msg2
.Printf(wxT("non-object data at $%lX, size %d"), (long)GetActualData(), (int)RequestSize() ); 
 413   Validate a node. Check to see that the node is "clean" in the sense 
 414   that nothing has over/underwritten it etc. 
 416 int wxMemStruct::ValidateNode () 
 418     char * startPointer 
= (char *) this; 
 421             ErrorMsg ("Object already deleted"); 
 423             // Can't use the error routines as we have no recognisable object. 
 425              wxLogMessage(wxT("Can't verify memory struct - all bets are off!")); 
 433     for (i = 0; i < wxDebugContext::TotSize (requestSize ()); i++) 
 434       cout << startPointer [i]; 
 437     if (Marker () != MemStartCheck
) 
 439     if (* (wxMarkerType 
*) wxDebugContext::MidMarkerPos (startPointer
) != MemMidCheck
) 
 441     if (* (wxMarkerType 
*) wxDebugContext::EndMarkerPos (startPointer
, 
 446     // Back to before the extra buffer and check that 
 447     // we can still read what we originally wrote. 
 448     if (Marker () != MemStartCheck 
|| 
 449         * (wxMarkerType 
*) wxDebugContext::MidMarkerPos (startPointer
) 
 451         * (wxMarkerType 
*) wxDebugContext::EndMarkerPos (startPointer
, 
 452                                               RequestSize ()) != MemEndCheck
) 
 462   The wxDebugContext class. 
 465 wxMemStruct 
*wxDebugContext::m_head 
= NULL
; 
 466 wxMemStruct 
*wxDebugContext::m_tail 
= NULL
; 
 467 // wxSTD ostream *wxDebugContext::m_debugStream = NULL; 
 468 // wxSTD streambuf *wxDebugContext::m_streamBuf = NULL; 
 470 // Must initialise these in wxEntry, and then delete them just before wxEntry exits 
 473 wxSTD streambuf 
*wxDebugContext::m_streamBuf 
= NULL
; 
 474 wxSTD ostream 
*wxDebugContext::m_debugStream 
= NULL
; 
 477 bool wxDebugContext::m_checkPrevious 
= FALSE
; 
 478 int wxDebugContext::debugLevel 
= 1; 
 479 bool wxDebugContext::debugOn 
= TRUE
; 
 480 wxMemStruct 
*wxDebugContext::checkPoint 
= NULL
; 
 482 // For faster alignment calculation 
 483 static wxMarkerType markerCalc
[2]; 
 484 int wxDebugContext::m_balign 
= (int)((char *)&markerCalc
[1] - (char*)&markerCalc
[0]); 
 485 int wxDebugContext::m_balignmask 
= (int)((char *)&markerCalc
[1] - (char*)&markerCalc
[0]) - 1; 
 487 wxDebugContext::wxDebugContext(void) 
 489 //  m_streamBuf = new wxDebugStreamBuf; 
 490 //  m_debugStream = new wxSTD ostream(m_streamBuf); 
 493 wxDebugContext::~wxDebugContext(void) 
 495 //  SetStream(NULL, NULL); 
 499  * It's bizarre, but with BC++ 4.5, the value of str changes 
 500  * between SetFile and SetStream. 
 505 void wxDebugContext::SetStream(wxSTD ostream 
*str
, wxSTD streambuf 
*buf
) 
 509     m_debugStream
->flush(); 
 510     delete m_debugStream
; 
 512   m_debugStream 
= NULL
; 
 514   // Not allowed in Watcom (~streambuf is protected). 
 515   // Is this trying to say something significant to us?? 
 519     wxSTD streambuf
* oldBuf 
= m_streamBuf
; 
 528 bool wxDebugContext::SetFile(const wxString
& file
) 
 530   wxSTD ofstream 
*str 
= new wxSTD 
ofstream(file
.mb_str()); 
 544 bool wxDebugContext::SetStandardError(void) 
 548 #if !defined(_WINDLL) 
 549   wxDebugStreamBuf 
*buf 
= new wxDebugStreamBuf
; 
 550   wxSTD ostream 
*stream 
= new wxSTD 
ostream(m_streamBuf
); 
 551   SetStream(stream
, buf
); 
 563   Work out the positions of the markers by creating an array of 2 markers 
 564   and comparing the addresses of the 2 elements. Use this number as the 
 565   alignment for markers. 
 567 size_t wxDebugContext::CalcAlignment () 
 570     return (char *) &ar
[1] - (char *) &ar
[0]; 
 574 char * wxDebugContext::StructPos (const char * buf
) 
 579 char * wxDebugContext::MidMarkerPos (const char * buf
) 
 581     return StructPos (buf
) + PaddedSize (sizeof (wxMemStruct
)); 
 584 char * wxDebugContext::CallerMemPos (const char * buf
) 
 586     return MidMarkerPos (buf
) + PaddedSize (sizeof(wxMarkerType
)); 
 590 char * wxDebugContext::EndMarkerPos (const char * buf
, const size_t size
) 
 592     return CallerMemPos (buf
) + PaddedSize (size
); 
 597   Slightly different as this takes a pointer to the start of the caller 
 598   requested region and returns a pointer to the start of the buffer. 
 600 char * wxDebugContext::StartPos (const char * caller
) 
 602     return ((char *) (caller 
- wxDebugContext::PaddedSize (sizeof(wxMarkerType
)) - 
 603             wxDebugContext::PaddedSize (sizeof (wxMemStruct
)))); 
 607   We may need padding between various parts of the allocated memory. 
 608   Given a size of memory, this returns the amount of memory which should 
 609   be allocated in order to allow for alignment of the following object. 
 611   I don't know how portable this stuff is, but it seems to work for me at 
 612   the moment. It would be real nice if I knew more about this! 
 614   // Note: this function is now obsolete (along with CalcAlignment) 
 615   // because the calculations are done statically, for greater speed. 
 617 size_t wxDebugContext::GetPadding (const size_t size
) 
 619     size_t pad 
= size 
% CalcAlignment (); 
 620     return (pad
) ? sizeof(wxMarkerType
) - pad 
: 0; 
 623 size_t wxDebugContext::PaddedSize (const size_t size
) 
 625     // Added by Terry Farnham <TJRT@pacbell.net> to replace 
 626     // slow GetPadding call. 
 629     padb 
= size 
& m_balignmask
; 
 631         return(size 
+ m_balign 
- padb
); 
 637     return size 
+ GetPadding (size
); 
 642   Returns the total amount of memory which we need to get from the system 
 643   in order to satisfy a caller request. This includes space for the struct 
 644   plus markers and the caller's memory as well. 
 646 size_t wxDebugContext::TotSize (const size_t reqSize
) 
 648     return (PaddedSize (sizeof (wxMemStruct
)) + PaddedSize (reqSize
) + 
 649             2 * sizeof(wxMarkerType
)); 
 654   Traverse the list of nodes executing the given function on each node. 
 656 void wxDebugContext::TraverseList (PmSFV func
, wxMemStruct 
*from
) 
 659     from 
= wxDebugContext::GetHead (); 
 661   wxMemStruct 
* st 
= NULL
; 
 662   for (st 
= from
; st 
!= 0; st 
= st
->m_next
) 
 664       void* data 
= st
->GetActualData(); 
 665 //      if ((data != (void*)m_debugStream) && (data != (void*) m_streamBuf)) 
 666       if (data 
!= (void*) wxLog::GetActiveTarget()) 
 677 bool wxDebugContext::PrintList (void) 
 683   TraverseList ((PmSFV
)&wxMemStruct::PrintNode
, (checkPoint 
? checkPoint
->m_next 
: (wxMemStruct
*)NULL
)); 
 691 bool wxDebugContext::Dump(void) 
 699     wxChar
* appName 
= (wxChar
*) wxT("application"); 
 700     wxString 
appNameStr(""); 
 703         appNameStr 
= wxTheApp
->GetAppName(); 
 704         appName 
= WXSTRINGCAST appNameStr
; 
 705         wxLogMessage(wxT("----- Memory dump of %s at %s -----"), appName
, WXSTRINGCAST 
wxNow() ); 
 709       wxLogMessage( wxT("----- Memory dump -----") ); 
 712   TraverseList ((PmSFV
)&wxMemStruct::Dump
, (checkPoint 
? checkPoint
->m_next 
: (wxMemStruct
*)NULL
)); 
 714   wxLogMessage( wxT("") ); 
 715   wxLogMessage( wxT("") ); 
 724 struct wxDebugStatsStruct
 
 728   wxChar 
*instanceClass
; 
 729   wxDebugStatsStruct 
*next
; 
 732 static wxDebugStatsStruct 
*FindStatsStruct(wxDebugStatsStruct 
*st
, wxChar 
*name
) 
 736     if (wxStrcmp(st
->instanceClass
, name
) == 0) 
 743 static wxDebugStatsStruct 
*InsertStatsStruct(wxDebugStatsStruct 
*head
, wxDebugStatsStruct 
*st
) 
 750 bool wxDebugContext::PrintStatistics(bool detailed
) 
 758     wxChar
* appName 
= (wxChar
*) wxT("application"); 
 759     wxString 
appNameStr(wxT("")); 
 762         appNameStr 
= wxTheApp
->GetAppName(); 
 763         appName 
= WXSTRINGCAST appNameStr
; 
 764         wxLogMessage(wxT("----- Memory statistics of %s at %s -----"), appName
, WXSTRINGCAST 
wxNow() ); 
 768       wxLogMessage( wxT("----- Memory statistics -----") ); 
 772   bool currentMode 
= GetDebugMode(); 
 775   long noNonObjectNodes 
= 0; 
 776   long noObjectNodes 
= 0; 
 779   wxDebugStatsStruct 
*list 
= NULL
; 
 781   wxMemStruct 
*from 
= (checkPoint 
? checkPoint
->m_next 
: (wxMemStruct
*)NULL 
); 
 783     from 
= wxDebugContext::GetHead (); 
 786   for (st 
= from
; st 
!= 0; st 
= st
->m_next
) 
 788     void* data 
= st
->GetActualData(); 
 789 //    if (detailed && (data != (void*)m_debugStream) && (data != (void*) m_streamBuf)) 
 790       if (detailed 
&& (data 
!= (void*) wxLog::GetActiveTarget())) 
 792       wxChar 
*className 
= (wxChar
*) wxT("nonobject"); 
 793       if (st
->m_isObject 
&& st
->GetActualData()) 
 795         wxObject 
*obj 
= (wxObject 
*)st
->GetActualData(); 
 796         if (obj
->GetClassInfo()->GetClassName()) 
 797           className 
= (wxChar
*)obj
->GetClassInfo()->GetClassName(); 
 799       wxDebugStatsStruct 
*stats 
= FindStatsStruct(list
, className
); 
 802         stats 
= (wxDebugStatsStruct 
*)malloc(sizeof(wxDebugStatsStruct
)); 
 803         stats
->instanceClass 
= className
; 
 804         stats
->instanceCount 
= 0; 
 805         stats
->totalSize 
= 0; 
 806         list 
= InsertStatsStruct(list
, stats
); 
 808       stats
->instanceCount 
++; 
 809       stats
->totalSize 
+= st
->RequestSize(); 
 812 //    if ((data != (void*)m_debugStream) && (data != (void*) m_streamBuf)) 
 813     if (data 
!= (void*) wxLog::GetActiveTarget()) 
 815         totalSize 
+= st
->RequestSize(); 
 827       wxLogMessage(wxT("%ld objects of class %s, total size %ld"), 
 828           list
->instanceCount
, list
->instanceClass
, list
->totalSize
); 
 829       wxDebugStatsStruct 
*old 
= list
; 
 833     wxLogMessage(wxT("")); 
 836   SetDebugMode(currentMode
); 
 838   wxLogMessage(wxT("Number of object items: %ld"), noObjectNodes
); 
 839   wxLogMessage(wxT("Number of non-object items: %ld"), noNonObjectNodes
); 
 840   wxLogMessage(wxT("Total allocated size: %ld"), totalSize
); 
 841   wxLogMessage(wxT("")); 
 842   wxLogMessage(wxT("")); 
 851 bool wxDebugContext::PrintClasses(void) 
 858     wxChar
* appName 
= (wxChar
*) wxT("application"); 
 859     wxString 
appNameStr(wxT("")); 
 862         appNameStr 
= wxTheApp
->GetAppName(); 
 863         appName 
= WXSTRINGCAST appNameStr
; 
 864         wxLogMessage(wxT("----- Classes in %s -----"), appName
); 
 872   wxClassInfo::sm_classTable
->BeginFind(); 
 873   node 
= wxClassInfo::sm_classTable
->Next(); 
 876     info 
= (wxClassInfo 
*)node
->Data(); 
 877     if (info
->GetClassName()) 
 879         wxString 
msg(info
->GetClassName()); 
 882         if (info
->GetBaseClassName1() && !info
->GetBaseClassName2()) 
 885             msg 
+= info
->GetBaseClassName1(); 
 887         else if (info
->GetBaseClassName1() && info
->GetBaseClassName2()) 
 890             msg 
+= info
->GetBaseClassName1() ; 
 892             msg 
+= info
->GetBaseClassName2() ; 
 894         if (info
->GetConstructor()) 
 895             msg 
+= wxT(": dynamic"); 
 899     node 
= wxClassInfo::sm_classTable
->Next(); 
 902   wxLogMessage(wxT("")); 
 903   wxLogMessage(wxT("There are %d classes derived from wxObject."), n
); 
 904   wxLogMessage(wxT("")); 
 905   wxLogMessage(wxT("")); 
 909 void wxDebugContext::SetCheckpoint(bool all
) 
 917 // Checks all nodes since checkpoint, or since start. 
 918 int wxDebugContext::Check(bool checkAll
) 
 922   wxMemStruct 
*from 
= (checkPoint 
? checkPoint
->m_next 
: (wxMemStruct
*)NULL 
); 
 923   if (!from 
|| checkAll
) 
 924     from 
= wxDebugContext::GetHead (); 
 926   for (wxMemStruct 
* st 
= from
; st 
!= 0; st 
= st
->m_next
) 
 929       nFailures 
+= st
->CheckBlock (); 
 937 // Count the number of non-wxDebugContext-related objects 
 938 // that are outstanding 
 939 int wxDebugContext::CountObjectsLeft(bool sinceCheckpoint
) 
 943   wxMemStruct 
*from 
= NULL
; 
 944   if (sinceCheckpoint 
&& checkPoint
) 
 945     from 
= checkPoint
->m_next
; 
 947     from 
= wxDebugContext::GetHead () ; 
 949   for (wxMemStruct 
* st 
= from
; st 
!= 0; st 
= st
->m_next
) 
 951       void* data 
= st
->GetActualData(); 
 952 //      if ((data != (void*)m_debugStream) && (data != (void*) m_streamBuf)) 
 953       if (data 
!= (void*) wxLog::GetActiveTarget()) 
 960 // TODO: store whether this is a vector or not. 
 961 void * wxDebugAlloc(size_t size
, wxChar 
* fileName
, int lineNum
, bool isObject
, bool WXUNUSED(isVect
) ) 
 963   // If not in debugging allocation mode, do the normal thing 
 964   // so we don't leave any trace of ourselves in the node list. 
 966 #if defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ) 
 967 // VA 3.0 still has trouble in here 
 968   return (void *)malloc(size
); 
 970   if (!wxDebugContext::GetDebugMode()) 
 972     return (void *)malloc(size
); 
 975     int totSize 
= wxDebugContext::TotSize (size
); 
 976     char * buf 
= (char *) malloc(totSize
); 
 978         wxLogMessage(wxT("Call to malloc (%ld) failed."), (long)size
); 
 981     wxMemStruct 
* st 
= (wxMemStruct 
*)buf
; 
 982     st
->m_firstMarker 
= MemStartCheck
; 
 983     st
->m_reqSize 
= size
; 
 984     st
->m_fileName 
= fileName
; 
 985     st
->m_lineNum 
= lineNum
; 
 986     st
->m_id 
= MemStructId
; 
 989     st
->m_isObject 
= isObject
; 
 991     // Errors from Append() shouldn't really happen - but just in case! 
 992     if (st
->Append () == 0) { 
 993         st
->ErrorMsg ("Trying to append new node"); 
 996     if (wxDebugContext::GetCheckPrevious ()) { 
 997         if (st
->CheckAllPrevious () < 0) { 
 998             st
->ErrorMsg ("Checking previous nodes"); 
1002     // Set up the extra markers at the middle and end. 
1003     char * ptr 
= wxDebugContext::MidMarkerPos (buf
); 
1004     * (wxMarkerType 
*) ptr 
= MemMidCheck
; 
1005     ptr 
= wxDebugContext::EndMarkerPos (buf
, size
); 
1006     * (wxMarkerType 
*) ptr 
= MemEndCheck
; 
1008     // pointer returned points to the start of the caller's 
1010     void *m_actualData 
= (void *) wxDebugContext::CallerMemPos (buf
); 
1011     st
->m_actualData 
= m_actualData
; 
1013     return m_actualData
; 
1016 // TODO: check whether was allocated as a vector 
1017 void wxDebugFree(void * buf
, bool WXUNUSED(isVect
) ) 
1022 #if defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ) 
1023 // VA 3.0 still has trouble in here 
1026   // If not in debugging allocation mode, do the normal thing 
1027   // so we don't leave any trace of ourselves in the node list. 
1028   if (!wxDebugContext::GetDebugMode()) 
1034     // Points to the start of the entire allocated area. 
1035     char * startPointer 
= wxDebugContext::StartPos ((char *) buf
); 
1036     // Find the struct and make sure that it's identifiable. 
1037     wxMemStruct 
* st 
= (wxMemStruct 
*) wxDebugContext::StructPos (startPointer
); 
1039     if (! st
->ValidateNode ()) 
1042     // If this is the current checkpoint, we need to 
1043     // move the checkpoint back so it points to a valid 
1045     if (st 
== wxDebugContext::checkPoint
) 
1046       wxDebugContext::checkPoint 
= wxDebugContext::checkPoint
->m_prev
; 
1048     if (! st
->Unlink ()) 
1050       st
->ErrorMsg ("Unlinking deleted node"); 
1053     // Now put in the fill char into the id slot and the caller requested 
1054     // memory locations. 
1056     (void) memset (wxDebugContext::CallerMemPos (startPointer
), MemFillChar
, 
1057                    st
->RequestSize ()); 
1059     // Don't allow delayed freeing of memory in this version 
1060 //    if (!wxDebugContext::GetDelayFree()) 
1061 //    free((void *)st); 
1065 // Trace: send output to the current debugging stream 
1066 void wxTrace(const wxChar 
* ...) 
1069     wxFAIL_MSG(wxT("wxTrace is now obsolete. Please use wxDebugXXX instead.")); 
1072   static wxChar buffer
[512]; 
1077   wvsprintf(buffer
,fmt
,ap
) ; 
1079   vsprintf(buffer
,fmt
,ap
) ; 
1084   if (wxDebugContext::HasStream()) 
1086     wxDebugContext::GetStream() << buffer
; 
1087     wxDebugContext::GetStream().flush(); 
1092     OutputDebugString((LPCTSTR
)buffer
) ; 
1094     OutputDebugString((const char*) buffer
) ; 
1097     fprintf(stderr
, buffer
); 
1103 void wxTraceLevel(int, const wxChar 
* ...) 
1106     wxFAIL_MSG(wxT("wxTrace is now obsolete. Please use wxDebugXXX instead.")); 
1108   if (wxDebugContext::GetLevel() < level
) 
1112   static wxChar buffer
[512]; 
1117   wxWvsprintf(buffer
,fmt
,ap
) ; 
1119   vsprintf(buffer
,fmt
,ap
) ; 
1124   if (wxDebugContext::HasStream()) 
1126     wxDebugContext::GetStream() << buffer
; 
1127     wxDebugContext::GetStream().flush(); 
1132     OutputDebugString((LPCTSTR
)buffer
) ; 
1134     OutputDebugString((const char*) buffer
) ; 
1137     fprintf(stderr
, buffer
); 
1142 #else // wxUSE_MEMORY_TRACING && defined(__WXDEBUG__) 
1143 void wxTrace(const char *WXUNUSED(fmt
) ...) 
1147 void wxTraceLevel(int WXUNUSED(level
), const char *WXUNUSED(fmt
) ...)