]> git.saurik.com Git - wxWidgets.git/blob - src/common/memory.cpp
New virtual key defines (NUMPAD_XXX).
[wxWidgets.git] / src / common / memory.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        memory.cpp
3 // Purpose:     Memory checking implementation
4 // Author:      Arthur Seaton, Julian Smart
5 // Modified by:
6 // Created:     04/01/98
7 // RCS-ID:      $Id$
8 // Copyright:   (c) Julian Smart and Markus Holzem
9 // Licence:     wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "memory.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/defs.h"
25 #endif
26
27 #if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
28
29 #ifdef __GNUG__
30 // #pragma implementation
31 #endif
32
33 #ifndef WX_PRECOMP
34 #include "wx/utils.h"
35 #include "wx/app.h"
36 #endif
37
38 #include <wx/log.h>
39 #include <stdlib.h>
40
41 #include "wx/ioswrap.h"
42
43 #if wxUSE_IOSTREAMH
44     #include <fstream.h>
45 #else
46     #include <fstream>
47 #endif
48
49 #if !defined(__WATCOMC__) && !defined(__VMS__) && !defined( __MWERKS__ ) && !defined(__SALFORDC__)
50 #include <memory.h>
51 #endif
52
53 #include <stdarg.h>
54 #include <string.h>
55
56 #ifdef __WXMSW__
57 #include <windows.h>
58
59 #ifdef GetClassInfo
60 #undef GetClassInfo
61 #endif
62
63 #ifdef GetClassName
64 #undef GetClassName
65 #endif
66
67 #endif
68
69 #include "wx/memory.h"
70
71 #ifdef new
72 #undef new
73 #endif
74
75 // wxDebugContext wxTheDebugContext;
76 /*
77   Redefine new and delete so that we can pick up situations where:
78         - we overwrite or underwrite areas of malloc'd memory.
79         - we use uninitialise variables
80   Only do this in debug mode.
81
82   We change new to get enough memory to allocate a struct, followed
83   by the caller's requested memory, followed by a tag. The struct
84   is used to create a doubly linked list of these areas and also
85   contains another tag. The tags are used to determine when the area
86   has been over/under written.
87 */
88
89
90 /*
91   Values which are used to set the markers which will be tested for
92   under/over write. There are 3 of these, one in the struct, one
93   immediately after the struct but before the caller requested memory and
94   one immediately after the requested memory.
95 */
96 #define MemStartCheck  0x23A8
97 #define MemMidCheck  0xA328
98 #define MemEndCheck 0x8A32
99 #define MemFillChar 0xAF
100 #define MemStructId  0x666D
101
102 /*
103   External interface for the wxMemStruct class. Others are
104   defined inline within the class def. Here we only need to be able
105   to add and delete nodes from the list and handle errors in some way.
106 */
107
108 /*
109   Used for internal "this shouldn't happen" type of errors.
110 */
111 void wxMemStruct::ErrorMsg (const char * mesg)
112 {
113   wxLogDebug(_T("wxWindows memory checking error: %s"), mesg);
114   PrintNode ();
115
116 //         << m_fileName << ' ' << m_lineNum << endl;
117 }
118
119 /*
120   Used when we find an overwrite or an underwrite error.
121 */
122 void wxMemStruct::ErrorMsg ()
123 {
124   wxLogDebug(_T("wxWindows over/underwrite memory error:"));
125   PrintNode ();
126
127 //    cerr << m_fileName << ' ' << m_lineNum << endl;
128 }
129
130
131 /*
132   We want to find out if pointers have been overwritten as soon as is
133   possible, so test everything before we dereference it. Of course it's still
134   quite possible that, if things have been overwritten, this function will
135   fall over, but the only way of dealing with that would cost too much in terms
136   of time.
137 */
138 int wxMemStruct::AssertList ()
139 {
140     if (wxDebugContext::GetHead () != 0 && ! (wxDebugContext::GetHead ())->AssertIt () ||
141         wxDebugContext::GetTail () != 0 && ! wxDebugContext::GetTail ()->AssertIt ()) {
142         ErrorMsg ("Head or tail pointers trashed");
143         return 0;
144     }
145     return 1;
146 }
147
148
149 /*
150   Check that the thing we're pointing to has the correct id for a wxMemStruct
151   object and also that it's previous and next pointers are pointing at objects
152   which have valid ids.
153   This is definitely not perfect since we could fall over just trying to access
154   any of the slots which we use here, but I think it's about the best that I
155   can do without doing something like taking all new wxMemStruct pointers and
156   comparing them against all known pointer within the list and then only
157   doing this sort of check _after_ you've found the pointer in the list. That
158   would be safer, but also much more time consuming.
159 */
160 int wxMemStruct::AssertIt ()
161 {
162     return (m_id == MemStructId &&
163             (m_prev == 0 || m_prev->m_id == MemStructId) &&
164             (m_next == 0 || m_next->m_id == MemStructId));
165 }
166
167
168 /*
169   Additions are always at the tail of the list.
170   Returns 0 on error, non-zero on success.
171 */
172 int wxMemStruct::Append ()
173 {
174     if (! AssertList ())
175         return 0;
176
177     if (wxDebugContext::GetHead () == 0) {
178         if (wxDebugContext::GetTail () != 0) {
179             ErrorMsg ("Null list should have a null tail pointer");
180             return 0;
181         }
182         (void) wxDebugContext::SetHead (this);
183         (void) wxDebugContext::SetTail (this);
184     } else {
185         wxDebugContext::GetTail ()->m_next = this;
186         this->m_prev = wxDebugContext::GetTail ();
187         (void) wxDebugContext::SetTail (this);
188     }
189     return 1;
190 }
191
192
193 /*
194   Don't actually free up anything here as the space which is used
195   by the node will be free'd up when the whole block is free'd.
196   Returns 0 on error, non-zero on success.
197 */
198 int wxMemStruct::Unlink ()
199 {
200     if (! AssertList ())
201         return 0;
202
203     if (wxDebugContext::GetHead () == 0 || wxDebugContext::GetTail () == 0) {
204         ErrorMsg ("Trying to remove node from empty list");
205         return 0;
206     }
207
208     // Handle the part of the list before this node.
209     if (m_prev == 0) {
210         if (this != wxDebugContext::GetHead ()) {
211             ErrorMsg ("No previous node for non-head node");
212             return 0;
213         }
214         (void) wxDebugContext::SetHead (m_next);
215     } else {
216         if (! m_prev->AssertIt ()) {
217             ErrorMsg ("Trashed previous pointer");
218             return 0;
219         }
220
221         if (m_prev->m_next != this) {
222             ErrorMsg ("List is inconsistent");
223             return 0;
224         }
225         m_prev->m_next = m_next;
226     }
227
228     // Handle the part of the list after this node.
229     if (m_next == 0) {
230         if (this != wxDebugContext::GetTail ()) {
231             ErrorMsg ("No next node for non-tail node");
232             return 0;
233         }
234         (void) wxDebugContext::SetTail (m_prev);
235     } else {
236         if (! m_next->AssertIt ()) {
237             ErrorMsg ("Trashed next pointer");
238             return 0;
239         }
240
241         if (m_next->m_prev != this) {
242             ErrorMsg ("List is inconsistent");
243             return 0;
244         }
245         m_next->m_prev = m_prev;
246     }
247
248     return 1;
249 }
250
251
252
253 /*
254   Checks a node and block of memory to see that the markers are still
255   intact.
256 */
257 int wxMemStruct::CheckBlock ()
258 {
259     int nFailures = 0;
260
261     if (m_firstMarker != MemStartCheck) {
262         nFailures++;
263         ErrorMsg ();
264     }
265
266     char * pointer = wxDebugContext::MidMarkerPos ((char *) this);
267     if (* (wxMarkerType *) pointer != MemMidCheck) {
268         nFailures++;
269         ErrorMsg ();
270     }
271
272     pointer = wxDebugContext::EndMarkerPos ((char *) this, RequestSize ());
273     if (* (wxMarkerType *) pointer != MemEndCheck) {
274         nFailures++;
275         ErrorMsg ();
276     }
277
278     return nFailures;
279 }
280
281
282 /*
283   Check the list of nodes to see if they are all ok.
284 */
285 int wxMemStruct::CheckAllPrevious ()
286 {
287     int nFailures = 0;
288
289     for (wxMemStruct * st = this->m_prev; st != 0; st = st->m_prev) {
290         if (st->AssertIt ())
291             nFailures += st->CheckBlock ();
292         else
293             return -1;
294     }
295
296     return nFailures;
297 }
298
299
300 /*
301   When we delete a node we set the id slot to a specific value and then test
302   against this to see if a nodes have been deleted previously. I don't
303   just set the entire memory to the fillChar because then I'd be overwriting
304   useful stuff like the vtbl which may be needed to output the error message
305   including the file name and line numbers. Without this info the whole point
306   of this class is lost!
307 */
308 void wxMemStruct::SetDeleted ()
309 {
310     m_id = MemFillChar;
311 }
312
313 int wxMemStruct::IsDeleted ()
314 {
315     return (m_id == MemFillChar);
316 }
317
318
319 /*
320   Print out a single node. There are many far better ways of doing this
321   but this will suffice for now.
322 */
323 void wxMemStruct::PrintNode ()
324 {
325   if (m_isObject)
326   {
327     wxObject *obj = (wxObject *)m_actualData;
328     wxClassInfo *info = obj->GetClassInfo();
329
330     // Let's put this in standard form so IDEs can load the file at the appropriate
331     // line
332     wxString msg(_T(""));
333
334     if (m_fileName)
335       msg.Printf(_T("%s(%d): "), m_fileName, (int)m_lineNum);
336
337     if (info && info->GetClassName())
338       msg += info->GetClassName();
339     else
340       msg += _T("object");
341
342     wxString msg2;
343     msg2.Printf(_T(" at $%lX, size %d"), (long)GetActualData(), (int)RequestSize());
344     msg += msg2;
345
346     wxLogDebug(msg);
347   }
348   else
349   {
350     wxString msg("");
351
352     if (m_fileName)
353       msg.Printf(_T("%s(%d): "), m_fileName, (int)m_lineNum);
354     msg += _T("non-object data");
355     wxString msg2;
356     msg2.Printf(_T(" at $%lX, size %d\n"), (long)GetActualData(), (int)RequestSize());
357     msg += msg2;
358
359     wxLogDebug(msg);
360   }
361 }
362
363 void wxMemStruct::Dump ()
364 {
365   if (!ValidateNode()) return;
366
367   if (m_isObject)
368   {
369     wxObject *obj = (wxObject *)m_actualData;
370
371     wxString msg(_T(""));
372     if (m_fileName)
373       msg.Printf(_T("%s(%d): "), m_fileName, (int)m_lineNum);
374
375
376     /* TODO: We no longer have a stream (using wxLogDebug) so we can't dump it.
377      * Instead, do what wxObject::Dump does.
378      * What should we do long-term, eliminate Dumping? Or specify
379      * that MyClass::Dump should use wxLogDebug? Ugh.
380     obj->Dump(wxDebugContext::GetStream());
381      */
382
383     if (obj->GetClassInfo() && obj->GetClassInfo()->GetClassName())
384       msg += obj->GetClassInfo()->GetClassName();
385     else
386       msg += _T("unknown object class");
387
388     wxString msg2("");
389     msg2.Printf(_T(" at $%lX, size %d"), (long)GetActualData(), (int)RequestSize());
390     msg += msg2;
391
392     wxLogDebug(msg);
393   }
394   else
395   {
396     wxString msg(_T(""));
397     if (m_fileName)
398       msg.Printf(_T("%s(%d): "), m_fileName, (int)m_lineNum);
399
400     wxString msg2("");
401     msg2.Printf(_T("non-object data at $%lX, size %d"), (long)GetActualData(), (int)RequestSize() );
402     msg += msg2;
403     wxLogDebug(msg);
404   }
405 }
406
407
408 /*
409   Validate a node. Check to see that the node is "clean" in the sense
410   that nothing has over/underwritten it etc.
411 */
412 int wxMemStruct::ValidateNode ()
413 {
414     char * startPointer = (char *) this;
415     if (!AssertIt ()) {
416         if (IsDeleted ())
417             ErrorMsg ("Object already deleted");
418         else {
419             // Can't use the error routines as we have no recognisable object.
420 #ifndef __WXGTK__
421              wxLogDebug(_T("Can't verify memory struct - all bets are off!"));
422 #endif
423         }
424         return 0;
425     }
426
427 /*
428     int i;
429     for (i = 0; i < wxDebugContext::TotSize (requestSize ()); i++)
430       cout << startPointer [i];
431     cout << endl;
432 */
433     if (Marker () != MemStartCheck)
434       ErrorMsg ();
435     if (* (wxMarkerType *) wxDebugContext::MidMarkerPos (startPointer) != MemMidCheck)
436       ErrorMsg ();
437     if (* (wxMarkerType *) wxDebugContext::EndMarkerPos (startPointer,
438                                               RequestSize ()) !=
439         MemEndCheck)
440       ErrorMsg ();
441
442     // Back to before the extra buffer and check that
443     // we can still read what we originally wrote.
444     if (Marker () != MemStartCheck ||
445         * (wxMarkerType *) wxDebugContext::MidMarkerPos (startPointer)
446                          != MemMidCheck ||
447         * (wxMarkerType *) wxDebugContext::EndMarkerPos (startPointer,
448                                               RequestSize ()) != MemEndCheck)
449     {
450         ErrorMsg ();
451         return 0;
452     }
453
454     return 1;
455 }
456
457 /*
458   The wxDebugContext class.
459 */
460
461 wxMemStruct *wxDebugContext::m_head = NULL;
462 wxMemStruct *wxDebugContext::m_tail = NULL;
463 // ostream *wxDebugContext::m_debugStream = NULL;
464 // streambuf *wxDebugContext::m_streamBuf = NULL;
465
466 // Must initialise these in wxEntry, and then delete them just before wxEntry exits
467 streambuf *wxDebugContext::m_streamBuf = NULL;
468 ostream *wxDebugContext::m_debugStream = NULL;
469
470 bool wxDebugContext::m_checkPrevious = FALSE;
471 int wxDebugContext::debugLevel = 1;
472 bool wxDebugContext::debugOn = TRUE;
473 wxMemStruct *wxDebugContext::checkPoint = NULL;
474
475 wxDebugContext::wxDebugContext(void)
476 {
477 //  m_streamBuf = new wxDebugStreamBuf;
478 //  m_debugStream = new ostream(m_streamBuf);
479 }
480
481 wxDebugContext::~wxDebugContext(void)
482 {
483   SetStream(NULL, NULL);
484 }
485
486 /*
487  * It's bizarre, but with BC++ 4.5, the value of str changes
488  * between SetFile and SetStream.
489  */
490
491 void wxDebugContext::SetStream(ostream *str, streambuf *buf)
492 {
493   if (m_debugStream)
494   {
495     m_debugStream->flush();
496     delete m_debugStream;
497   }
498   m_debugStream = NULL;
499
500   // Not allowed in Watcom (~streambuf is protected).
501   // Is this trying to say something significant to us??
502 #ifndef __WATCOMC__
503   if (m_streamBuf)
504   {
505     streambuf* oldBuf = m_streamBuf;
506     m_streamBuf = NULL;
507     delete oldBuf;
508   }
509 #endif
510   m_streamBuf = buf;
511   m_debugStream = str;
512 }
513
514 bool wxDebugContext::SetFile(const wxString& file)
515 {
516   ofstream *str = new ofstream(file.fn_str());
517
518   if (str->bad())
519   {
520     delete str;
521     return FALSE;
522   }
523   else
524   {
525     SetStream(str);
526     return TRUE;
527   }
528 }
529
530 bool wxDebugContext::SetStandardError(void)
531 {
532     // Obsolete
533 #if 0
534 #if !defined(_WINDLL)
535   wxDebugStreamBuf *buf = new wxDebugStreamBuf;
536   ostream *stream = new ostream(m_streamBuf);
537   SetStream(stream, buf);
538   return TRUE;
539 #else
540   return FALSE;
541 #endif
542 #endif
543   return FALSE;
544 }
545
546
547 /*
548   Work out the positions of the markers by creating an array of 2 markers
549   and comparing the addresses of the 2 elements. Use this number as the
550   alignment for markers.
551 */
552 size_t wxDebugContext::CalcAlignment ()
553 {
554     wxMarkerType ar[2];
555     return (char *) &ar[1] - (char *) &ar[0];
556 }
557
558
559 char * wxDebugContext::StructPos (const char * buf)
560 {
561     return (char *) buf;
562 }
563
564 char * wxDebugContext::MidMarkerPos (const char * buf)
565 {
566     return StructPos (buf) + PaddedSize (sizeof (wxMemStruct));
567 }
568
569 char * wxDebugContext::CallerMemPos (const char * buf)
570 {
571     return MidMarkerPos (buf) + PaddedSize (sizeof(wxMarkerType));
572 }
573
574
575 char * wxDebugContext::EndMarkerPos (const char * buf, const size_t size)
576 {
577     return CallerMemPos (buf) + PaddedSize (size);
578 }
579
580
581 /*
582   Slightly different as this takes a pointer to the start of the caller
583   requested region and returns a pointer to the start of the buffer.
584   */
585 char * wxDebugContext::StartPos (const char * caller)
586 {
587     return ((char *) (caller - wxDebugContext::PaddedSize (sizeof(wxMarkerType)) -
588             wxDebugContext::PaddedSize (sizeof (wxMemStruct))));
589 }
590
591 /*
592   We may need padding between various parts of the allocated memory.
593   Given a size of memory, this returns the amount of memory which should
594   be allocated in order to allow for alignment of the following object.
595
596   I don't know how portable this stuff is, but it seems to work for me at
597   the moment. It would be real nice if I knew more about this!
598 */
599 size_t wxDebugContext::GetPadding (const size_t size)
600 {
601     size_t pad = size % CalcAlignment ();
602     return (pad) ? sizeof(wxMarkerType) - pad : 0;
603 }
604
605
606
607 size_t wxDebugContext::PaddedSize (const size_t size)
608 {
609     return size + GetPadding (size);
610 }
611
612 /*
613   Returns the total amount of memory which we need to get from the system
614   in order to satisfy a caller request. This includes space for the struct
615   plus markers and the caller's memory as well.
616 */
617 size_t wxDebugContext::TotSize (const size_t reqSize)
618 {
619     return (PaddedSize (sizeof (wxMemStruct)) + PaddedSize (reqSize) +
620             2 * sizeof(wxMarkerType));
621 }
622
623
624 /*
625   Traverse the list of nodes executing the given function on each node.
626 */
627 void wxDebugContext::TraverseList (PmSFV func, wxMemStruct *from)
628 {
629   if (!from)
630     from = wxDebugContext::GetHead ();
631
632   for (wxMemStruct * st = from; st != 0; st = st->m_next)
633   {
634       void* data = st->GetActualData();
635 //      if ((data != (void*)m_debugStream) && (data != (void*) m_streamBuf))
636       if (data != (void*) wxLog::GetActiveTarget())
637       {
638         (st->*func) ();
639       }
640   }
641 }
642
643
644 /*
645   Print out the list.
646   */
647 bool wxDebugContext::PrintList (void)
648 {
649 #ifdef __WXDEBUG__
650 //  if (!HasStream())
651 //    return FALSE;
652
653   TraverseList ((PmSFV)&wxMemStruct::PrintNode, (checkPoint ? checkPoint->m_next : (wxMemStruct*)NULL));
654
655   return TRUE;
656 #else
657   return FALSE;
658 #endif
659 }
660
661 bool wxDebugContext::Dump(void)
662 {
663 #ifdef __WXDEBUG__
664 //  if (!HasStream())
665 //    return FALSE;
666
667   if (TRUE)
668   {
669     wxChar* appName = _T("application");
670     wxString appNameStr("");
671     if (wxTheApp)
672     {
673         appNameStr = wxTheApp->GetAppName();
674         appName = WXSTRINGCAST appNameStr;
675         wxLogDebug(_T("----- Memory dump of %s at %s -----"), appName, WXSTRINGCAST wxNow() );
676     }
677     else
678     {
679       wxLogDebug( _T("----- Memory dump -----") );
680     }
681   }
682   TraverseList ((PmSFV)&wxMemStruct::Dump, (checkPoint ? checkPoint->m_next : (wxMemStruct*)NULL));
683
684   wxLogDebug( _T("") );
685   wxLogDebug( _T("") );
686
687   return TRUE;
688 #else
689   return FALSE;
690 #endif
691 }
692
693 struct wxDebugStatsStruct
694 {
695   long instanceCount;
696   long totalSize;
697   wxChar *instanceClass;
698   wxDebugStatsStruct *next;
699 };
700
701 static wxDebugStatsStruct *FindStatsStruct(wxDebugStatsStruct *st, wxChar *name)
702 {
703   while (st)
704   {
705     if (wxStrcmp(st->instanceClass, name) == 0)
706       return st;
707     st = st->next;
708   }
709   return NULL;
710 }
711
712 static wxDebugStatsStruct *InsertStatsStruct(wxDebugStatsStruct *head, wxDebugStatsStruct *st)
713 {
714   st->next = head;
715   return st;
716 }
717
718 bool wxDebugContext::PrintStatistics(bool detailed)
719 {
720 #ifdef __WXDEBUG__
721 //  if (!HasStream())
722 //    return FALSE;
723
724   if (TRUE)
725   {
726     wxChar* appName = _T("application");
727     wxString appNameStr(_T(""));
728     if (wxTheApp)
729     {
730         appNameStr = wxTheApp->GetAppName();
731         appName = WXSTRINGCAST appNameStr;
732         wxLogDebug(_T("----- Memory statistics of %s at %s -----"), appName, WXSTRINGCAST wxNow() );
733     }
734     else
735     {
736       wxLogDebug( _T("----- Memory statistics -----") );
737     }
738   }
739
740   bool currentMode = GetDebugMode();
741   SetDebugMode(FALSE);
742
743   long noNonObjectNodes = 0;
744   long noObjectNodes = 0;
745   long totalSize = 0;
746
747   wxDebugStatsStruct *list = NULL;
748
749   wxMemStruct *from = (checkPoint ? checkPoint->m_next : (wxMemStruct*)NULL );
750   if (!from)
751     from = wxDebugContext::GetHead ();
752
753   wxMemStruct *st;
754   for (st = from; st != 0; st = st->m_next)
755   {
756     void* data = st->GetActualData();
757 //    if (detailed && (data != (void*)m_debugStream) && (data != (void*) m_streamBuf))
758       if (detailed && (data != (void*) wxLog::GetActiveTarget()))
759     {
760       wxChar *className = _T("nonobject");
761       if (st->m_isObject && st->GetActualData())
762       {
763         wxObject *obj = (wxObject *)st->GetActualData();
764         if (obj->GetClassInfo()->GetClassName())
765           className = obj->GetClassInfo()->GetClassName();
766       }
767       wxDebugStatsStruct *stats = FindStatsStruct(list, className);
768       if (!stats)
769       {
770         stats = (wxDebugStatsStruct *)malloc(sizeof(wxDebugStatsStruct));
771         stats->instanceClass = className;
772         stats->instanceCount = 0;
773         stats->totalSize = 0;
774         list = InsertStatsStruct(list, stats);
775       }
776       stats->instanceCount ++;
777       stats->totalSize += st->RequestSize();
778     }
779
780 //    if ((data != (void*)m_debugStream) && (data != (void*) m_streamBuf))
781     if (data != (void*) wxLog::GetActiveTarget())
782     {
783         totalSize += st->RequestSize();
784         if (st->m_isObject)
785             noObjectNodes ++;
786         else
787             noNonObjectNodes ++;
788     }
789   }
790
791   if (detailed)
792   {
793     while (list)
794     {
795       wxLogDebug(_T("%ld objects of class %s, total size %ld"),
796           list->instanceCount, list->instanceClass, list->totalSize);
797       wxDebugStatsStruct *old = list;
798       list = old->next;
799       free((char *)old);
800     }
801     wxLogDebug(_T(""));
802   }
803
804   SetDebugMode(currentMode);
805
806   wxLogDebug(_T("Number of object items: %ld"), noObjectNodes);
807   wxLogDebug(_T("Number of non-object items: %ld"), noNonObjectNodes);
808   wxLogDebug(_T("Total allocated size: %ld"), totalSize);
809   wxLogDebug(_T(""));
810   wxLogDebug(_T(""));
811
812   return TRUE;
813 #else
814   return FALSE;
815 #endif
816 }
817
818 bool wxDebugContext::PrintClasses(void)
819 {
820 //  if (!HasStream())
821 //    return FALSE;
822
823   if (TRUE)
824   {
825     wxChar* appName = _T("application");
826     wxString appNameStr(_T(""));
827     if (wxTheApp)
828     {
829         appNameStr = wxTheApp->GetAppName();
830         appName = WXSTRINGCAST appNameStr;
831         wxLogDebug(_T("----- Classes in %s -----"), appName);
832     }
833   }
834
835   int n = 0;
836   wxNode *node;
837   wxClassInfo *info;
838
839   wxClassInfo::sm_classTable->BeginFind();
840   node = wxClassInfo::sm_classTable->Next();
841   while (node)
842   {
843     info = (wxClassInfo *)node->Data();
844     if (info->GetClassName())
845     {
846         wxString msg(info->GetClassName());
847         msg += _T(" ");
848
849         if (info->GetBaseClassName1() && !info->GetBaseClassName2())
850         {
851             msg += _T("is a ");
852             msg += info->GetBaseClassName1();
853         }
854         else if (info->GetBaseClassName1() && info->GetBaseClassName2())
855         {
856             msg += _T("is a ");
857             msg += info->GetBaseClassName1() ;
858             msg += _T(", ");
859             msg += info->GetBaseClassName2() ;
860         }
861         if (info->GetConstructor())
862             msg += _T(": dynamic");
863
864         wxLogDebug(msg);
865     }
866     node = wxClassInfo::sm_classTable->Next();
867     n ++;
868   }
869   wxLogDebug(_T(""));
870   wxLogDebug(_T("There are %d classes derived from wxObject."), n);
871   wxLogDebug(_T(""));
872   wxLogDebug(_T(""));
873   return TRUE;
874 }
875
876 void wxDebugContext::SetCheckpoint(bool all)
877 {
878   if (all)
879     checkPoint = NULL;
880   else
881     checkPoint = m_tail;
882 }
883
884 // Checks all nodes since checkpoint, or since start.
885 int wxDebugContext::Check(bool checkAll)
886 {
887   int nFailures = 0;
888
889   wxMemStruct *from = (checkPoint ? checkPoint->m_next : (wxMemStruct*)NULL );
890   if (!from || checkAll)
891     from = wxDebugContext::GetHead ();
892
893   for (wxMemStruct * st = from; st != 0; st = st->m_next)
894   {
895     if (st->AssertIt ())
896       nFailures += st->CheckBlock ();
897     else
898       return -1;
899   }
900
901   return nFailures;
902 }
903
904 // Count the number of non-wxDebugContext-related objects
905 // that are outstanding
906 int wxDebugContext::CountObjectsLeft(bool sinceCheckpoint)
907 {
908   int n = 0;
909
910   wxMemStruct *from = NULL;
911   if (sinceCheckpoint && checkPoint)
912     from = checkPoint->m_next;
913   else
914     from = wxDebugContext::GetHead () ;
915
916   for (wxMemStruct * st = from; st != 0; st = st->m_next)
917   {
918       void* data = st->GetActualData();
919 //      if ((data != (void*)m_debugStream) && (data != (void*) m_streamBuf))
920       if (data != (void*) wxLog::GetActiveTarget())
921           n ++;
922   }
923
924   return n ;
925 }
926
927 /*
928   The global operator new used for everything apart from getting
929   dynamic storage within this function itself.
930 */
931
932 // We'll only do malloc and free for the moment: leave the interesting
933 // stuff for the wxObject versions.
934
935 #if defined(__WXDEBUG__) && wxUSE_GLOBAL_MEMORY_OPERATORS
936
937 #ifdef new
938 #undef new
939 #endif
940
941 // Seems OK all of a sudden. Maybe to do with linking with multithreaded library?
942 #if 0 // def __VISUALC__
943 #define NO_DEBUG_ALLOCATION
944 #endif
945
946 // Unfortunately ~wxDebugStreamBuf doesn't work (VC++ 5) when we enable the debugging
947 // code. I have no idea why. In BC++ 4.5, we have a similar problem the debug
948 // stream myseriously changing pointer address between being passed from SetFile to SetStream.
949 // See docs/msw/issues.txt.
950 void * operator new (size_t size, wxChar * fileName, int lineNum)
951 {
952 #ifdef NO_DEBUG_ALLOCATION
953   return malloc(size);
954 #else
955   return wxDebugAlloc(size, fileName, lineNum, FALSE, FALSE);
956 #endif
957 }
958
959 // Added JACS 25/11/98
960 void * operator new (size_t size)
961 {
962 #ifdef NO_DEBUG_ALLOCATION
963   return malloc(size);
964 #else
965   return wxDebugAlloc(size, NULL, 0, FALSE);
966 #endif
967 }
968
969 #if wxUSE_ARRAY_MEMORY_OPERATORS
970 void * operator new[] (size_t size)
971 {
972 #ifdef NO_DEBUG_ALLOCATION
973   return malloc(size);
974 #else
975   return wxDebugAlloc(size, NULL, 0, FALSE, TRUE);
976 #endif
977 }
978 #endif
979
980 #if wxUSE_ARRAY_MEMORY_OPERATORS
981 void * operator new[] (size_t size, wxChar * fileName, int lineNum)
982 {
983 #ifdef NO_DEBUG_ALLOCATION
984   return malloc(size);
985 #else
986   return wxDebugAlloc(size, fileName, lineNum, FALSE, TRUE);
987 #endif
988 }
989 #endif
990
991 void operator delete (void * buf)
992 {
993 #ifdef NO_DEBUG_ALLOCATION
994   free((char*) buf);
995 #else
996   wxDebugFree(buf);
997 #endif
998 }
999
1000 // VC++ 6.0
1001 #if defined(__VISUALC__) && (__VISUALC__ >= 1200)
1002 void operator delete(void* pData, wxChar* /* fileName */, int /* lineNum */)
1003 {
1004 // ::operator delete(pData);
1005   // JACS 21/11/1998: surely we need to call wxDebugFree?
1006   wxDebugFree(pData, FALSE);
1007 }
1008 // New operator 21/11/1998
1009 void operator delete[](void* pData, char* /* fileName */, int /* lineNum */)
1010 {
1011   wxDebugFree(pData, TRUE);
1012 }
1013 #endif
1014
1015 #if wxUSE_ARRAY_MEMORY_OPERATORS
1016
1017 void operator delete[] (void * buf)
1018 {
1019 #ifdef NO_DEBUG_ALLOCATION
1020   free((char*) buf);
1021 #else
1022   wxDebugFree(buf, TRUE);
1023 #endif
1024 }
1025 #endif
1026
1027 #endif
1028
1029 // TODO: store whether this is a vector or not.
1030 void * wxDebugAlloc(size_t size, wxChar * fileName, int lineNum, bool isObject, bool WXUNUSED(isVect) )
1031 {
1032   // If not in debugging allocation mode, do the normal thing
1033   // so we don't leave any trace of ourselves in the node list.
1034
1035   if (!wxDebugContext::GetDebugMode())
1036   {
1037     return (void *)malloc(size);
1038   }
1039
1040     int totSize = wxDebugContext::TotSize (size);
1041     char * buf = (char *) malloc(totSize);
1042     if (!buf) {
1043         wxLogDebug(_T("Call to malloc (%ld) failed."), (long)size);
1044         return 0;
1045     }
1046     wxMemStruct * st = (wxMemStruct *)buf;
1047     st->m_firstMarker = MemStartCheck;
1048     st->m_reqSize = size;
1049     st->m_fileName = fileName;
1050     st->m_lineNum = lineNum;
1051     st->m_id = MemStructId;
1052     st->m_prev = 0;
1053     st->m_next = 0;
1054     st->m_isObject = isObject;
1055
1056     // Errors from Append() shouldn't really happen - but just in case!
1057     if (st->Append () == 0) {
1058         st->ErrorMsg ("Trying to append new node");
1059     }
1060
1061     if (wxDebugContext::GetCheckPrevious ()) {
1062         if (st->CheckAllPrevious () < 0) {
1063             st->ErrorMsg ("Checking previous nodes");
1064         }
1065     }
1066
1067     // Set up the extra markers at the middle and end.
1068     char * ptr = wxDebugContext::MidMarkerPos (buf);
1069     * (wxMarkerType *) ptr = MemMidCheck;
1070     ptr = wxDebugContext::EndMarkerPos (buf, size);
1071     * (wxMarkerType *) ptr = MemEndCheck;
1072
1073     // pointer returned points to the start of the caller's
1074     // usable area.
1075     void *m_actualData = (void *) wxDebugContext::CallerMemPos (buf);
1076     st->m_actualData = m_actualData;
1077
1078     return m_actualData;
1079 }
1080
1081 // TODO: check whether was allocated as a vector
1082 void wxDebugFree(void * buf, bool WXUNUSED(isVect) )
1083 {
1084   if (!buf)
1085     return;
1086
1087   // If not in debugging allocation mode, do the normal thing
1088   // so we don't leave any trace of ourselves in the node list.
1089   if (!wxDebugContext::GetDebugMode())
1090   {
1091     free((char *)buf);
1092     return;
1093   }
1094
1095     // Points to the start of the entire allocated area.
1096     char * startPointer = wxDebugContext::StartPos ((char *) buf);
1097     // Find the struct and make sure that it's identifiable.
1098     wxMemStruct * st = (wxMemStruct *) wxDebugContext::StructPos (startPointer);
1099
1100     if (! st->ValidateNode ())
1101         return;
1102
1103     // If this is the current checkpoint, we need to
1104     // move the checkpoint back so it points to a valid
1105     // node.
1106     if (st == wxDebugContext::checkPoint)
1107       wxDebugContext::checkPoint = wxDebugContext::checkPoint->m_prev;
1108
1109     if (! st->Unlink ())
1110     {
1111       st->ErrorMsg ("Unlinking deleted node");
1112     }
1113
1114     // Now put in the fill char into the id slot and the caller requested
1115     // memory locations.
1116     st->SetDeleted ();
1117     (void) memset (wxDebugContext::CallerMemPos (startPointer), MemFillChar,
1118                    st->RequestSize ());
1119
1120     // Don't allow delayed freeing of memory in this version
1121 //    if (!wxDebugContext::GetDelayFree())
1122 //    free((void *)st);
1123     free((char *)st);
1124 }
1125
1126 // Trace: send output to the current debugging stream
1127 void wxTrace(const wxChar *fmt ...)
1128 {
1129   va_list ap;
1130   static wxChar buffer[512];
1131
1132   va_start(ap, fmt);
1133
1134 #ifdef __WXMSW__
1135   wvsprintf(buffer,fmt,ap) ;
1136 #else
1137   vsprintf(buffer,fmt,ap) ;
1138 #endif
1139
1140   va_end(ap);
1141
1142   if (wxDebugContext::HasStream())
1143   {
1144     wxDebugContext::GetStream() << buffer;
1145     wxDebugContext::GetStream().flush();
1146   }
1147   else
1148 #ifdef __WXMSW__
1149     OutputDebugString((LPCTSTR)buffer) ;
1150 #else
1151     fprintf(stderr, buffer);
1152 #endif
1153 }
1154
1155 // Trace with level
1156 void wxTraceLevel(int level, const wxChar *fmt ...)
1157 {
1158   if (wxDebugContext::GetLevel() < level)
1159     return;
1160
1161   va_list ap;
1162   static wxChar buffer[512];
1163
1164   va_start(ap, fmt);
1165
1166 #ifdef __WXMSW__
1167   wvsprintf(buffer,fmt,ap) ;
1168 #else
1169   vsprintf(buffer,fmt,ap) ;
1170 #endif
1171
1172   va_end(ap);
1173
1174   if (wxDebugContext::HasStream())
1175   {
1176     wxDebugContext::GetStream() << buffer;
1177     wxDebugContext::GetStream().flush();
1178   }
1179   else
1180 #ifdef __WXMSW__
1181     OutputDebugString((LPCTSTR)buffer) ;
1182 #else
1183     fprintf(stderr, buffer);
1184 #endif
1185 }
1186
1187 #else // wxUSE_MEMORY_TRACING && defined(__WXDEBUG__)
1188 void wxTrace(const char *WXUNUSED(fmt) ...)
1189 {
1190 }
1191
1192 void wxTraceLevel(int WXUNUSED(level), const char *WXUNUSED(fmt) ...)
1193 {
1194 }
1195 #endif
1196