1
/////////////////////////////////////////////////////////////////////////////
3
// Purpose: MDI classes
4
// Author: Arthur Seaton, Julian Smart
7
// RCS-ID: $Id: memory.h,v 1.47 2005/02/09 21:36:08 JS Exp $
8
// Copyright: (c) 1998 Julian Smart
9
// Licence: wxWindows licence
10
/////////////////////////////////////////////////////////////////////////////
15
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
16
#pragma interface "memory.h"
20
#include "wx/string.h"
21
#include "wx/msgout.h"
24
The macro which will be expanded to include the file and line number
25
info, or to be a straight call to the new operator.
28
#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
34
WXDLLIMPEXP_BASE void * wxDebugAlloc(size_t size, wxChar * fileName, int lineNum, bool isObject, bool isVect = false);
35
WXDLLIMPEXP_BASE void wxDebugFree(void * buf, bool isVect = false);
37
//**********************************************************************************
39
The global operator new used for everything apart from getting
40
dynamic storage within this function itself.
43
// We'll only do malloc and free for the moment: leave the interesting
44
// stuff for the wxObject versions.
47
#if wxUSE_GLOBAL_MEMORY_OPERATORS
49
// Undefine temporarily (new is #defined in object.h) because we want to
50
// declare some new operators.
55
#if defined(__SUNCC__)
56
#define wxUSE_ARRAY_MEMORY_OPERATORS 0
57
#elif !( defined (__VISUALC__) && (__VISUALC__ <= 1020) ) || defined( __MWERKS__)
58
#define wxUSE_ARRAY_MEMORY_OPERATORS 1
59
#elif defined (__SGI_CC_)
60
// only supported by -n32 compilers
61
#ifndef __EDG_ABI_COMPATIBILITY_VERSION
62
#define wxUSE_ARRAY_MEMORY_OPERATORS 0
64
#elif !( defined (__VISUALC__) && (__VISUALC__ <= 1020) ) || defined( __MWERKS__)
65
#define wxUSE_ARRAY_MEMORY_OPERATORS 1
67
// ::operator new[] is a recent C++ feature, so assume it's not supported
68
#define wxUSE_ARRAY_MEMORY_OPERATORS 0
71
// devik 2000-8-29: All new/delete ops are now inline because they can't
72
// be marked as dllexport/dllimport. It then leads to weird bugs when
74
#if defined(__WXMSW__) && (defined(WXUSINGDLL) || defined(WXMAKINGDLL_BASE))
75
inline void * operator new (size_t size, wxChar * fileName, int lineNum)
77
return wxDebugAlloc(size, fileName, lineNum, FALSE, FALSE);
80
inline void * operator new (size_t size)
82
return wxDebugAlloc(size, NULL, 0, FALSE);
85
inline void operator delete (void * buf)
87
wxDebugFree(buf, FALSE);
90
#if wxUSE_ARRAY_MEMORY_OPERATORS
91
inline void * operator new[] (size_t size)
93
return wxDebugAlloc(size, NULL, 0, FALSE, TRUE);
96
inline void * operator new[] (size_t size, wxChar * fileName, int lineNum)
98
return wxDebugAlloc(size, fileName, lineNum, FALSE, TRUE);
101
inline void operator delete[] (void * buf)
103
wxDebugFree(buf, TRUE);
105
#endif // wxUSE_ARRAY_MEMORY_OPERATORS
109
void * operator new (size_t size, wxChar * fileName, int lineNum);
111
void * operator new (size_t size);
113
void operator delete (void * buf);
115
#if wxUSE_ARRAY_MEMORY_OPERATORS
116
void * operator new[] (size_t size);
118
void * operator new[] (size_t size, wxChar * fileName, int lineNum);
120
void operator delete[] (void * buf);
121
#endif // wxUSE_ARRAY_MEMORY_OPERATORS
122
#endif // defined(__WXMSW__) && (defined(WXUSINGDLL) || defined(WXMAKINGDLL_BASE))
124
// VC++ 6.0 and MWERKS
125
#if ( defined(__VISUALC__) && (__VISUALC__ >= 1200) ) || defined(__MWERKS__)
126
inline void operator delete(void* pData, wxChar* /* fileName */, int /* lineNum */)
128
wxDebugFree(pData, false);
130
inline void operator delete[](void* pData, wxChar* /* fileName */, int /* lineNum */)
132
wxDebugFree(pData, true);
134
#endif // __VISUALC__>=1200
135
#endif // wxUSE_GLOBAL_MEMORY_OPERATORS
136
#endif // __WXDEBUG__
138
//**********************************************************************************
140
typedef unsigned int wxMarkerType;
143
Define the struct which will be placed at the start of all dynamically
147
class WXDLLIMPEXP_BASE wxMemStruct {
149
friend class WXDLLIMPEXP_BASE wxDebugContext; // access to the m_next pointer for list traversal.
155
size_t RequestSize () { return m_reqSize; }
156
wxMarkerType Marker () { return m_firstMarker; }
158
// When an object is deleted we set the id slot to a specific value.
159
inline void SetDeleted ();
160
inline int IsDeleted ();
165
// Used to determine if the object is really a wxMemStruct.
166
// Not a foolproof test by any means, but better than none I hope!
169
// Do all validation on a node.
172
// Check the integrity of a node and of the list, node by node.
174
int CheckAllPrevious ();
176
// Print a single node.
179
// Called when the memory linking functions get an error.
180
void ErrorMsg (const char *);
183
inline void *GetActualData(void) const { return m_actualData; }
188
// Check for underwriting. There are 2 of these checks. This one
189
// inside the struct and another right after the struct.
190
wxMarkerType m_firstMarker;
192
// File name and line number are from cpp.
196
// The amount of memory requested by the caller.
199
// Used to try to verify that we really are dealing with an object
200
// of the required class. Can be 1 of 2 values these indicating a valid
201
// wxMemStruct object, or a deleted wxMemStruct object.
204
wxMemStruct * m_prev;
205
wxMemStruct * m_next;
212
typedef void (wxMemStruct::*PmSFV) ();
216
Debugging class. This will only have a single instance, but it's
217
a reasonable way to keep everything together and to make this
218
available for change if needed by someone else.
219
A lot of this stuff would be better off within the wxMemStruct class, but
220
it's stuff which we need to access at times when there is no wxMemStruct
221
object so we use this class instead. Think of it as a collection of
222
globals which have to do with the wxMemStruct class.
225
class WXDLLIMPEXP_BASE wxDebugContext {
228
// Used to set alignment for markers.
229
static size_t CalcAlignment ();
231
// Returns the amount of padding needed after something of the given
232
// size. This is so that when we cast pointers backwards and forwards
233
// the pointer value will be valid for a wxMarkerType.
234
static size_t GetPadding (const size_t size) ;
236
// Traverse the list.
237
static void TraverseList (PmSFV, wxMemStruct *from = NULL);
239
static int debugLevel;
242
static int m_balign; // byte alignment
243
static int m_balignmask; // mask for performing byte alignment
245
// Set a checkpoint to dump only the memory from
247
static wxMemStruct *checkPoint;
249
wxDebugContext(void);
250
~wxDebugContext(void);
252
static int GetLevel(void) { return debugLevel; }
253
static void SetLevel(int level) { debugLevel = level; }
255
static bool GetDebugMode(void) { return debugOn; }
256
static void SetDebugMode(bool flag) { debugOn = flag; }
258
static void SetCheckpoint(bool all = false);
259
static wxMemStruct *GetCheckpoint(void) { return checkPoint; }
261
// Calculated from the request size and any padding needed
262
// before the final marker.
263
static size_t PaddedSize (const size_t reqSize);
265
// Calc the total amount of space we need from the system
266
// to satisfy a caller request. This includes all padding.
267
static size_t TotSize (const size_t reqSize);
269
// Return valid pointers to offsets within the allocated memory.
270
static char * StructPos (const char * buf);
271
static char * MidMarkerPos (const char * buf);
272
static char * CallerMemPos (const char * buf);
273
static char * EndMarkerPos (const char * buf, const size_t size);
275
// Given a pointer to the start of the caller requested area
276
// return a pointer to the start of the entire alloc\'d buffer.
277
static char * StartPos (const char * caller);
279
// Access to the list.
280
static wxMemStruct * GetHead () { return m_head; }
281
static wxMemStruct * GetTail () { return m_tail; }
283
// Set the list sentinals.
284
static wxMemStruct * SetHead (wxMemStruct * st) { return (m_head = st); }
285
static wxMemStruct * SetTail (wxMemStruct * st) { return (m_tail = st); }
287
// If this is set then every new operation checks the validity
288
// of the all previous nodes in the list.
289
static bool GetCheckPrevious () { return m_checkPrevious; }
290
static void SetCheckPrevious (bool value) { m_checkPrevious = value; }
292
// Checks all nodes, or all nodes if checkAll is true
293
static int Check(bool checkAll = false);
295
// Print out the list of wxMemStruct nodes.
296
static bool PrintList(void);
299
static bool Dump(void);
302
static bool PrintStatistics(bool detailed = true);
304
// Print out the classes in the application.
305
static bool PrintClasses(void);
307
// Count the number of non-wxDebugContext-related objects
308
// that are outstanding
309
static int CountObjectsLeft(bool sinceCheckpoint = false);
311
// This function is used to output the dump
312
static void OutputDumpLine(const wxChar *szFormat, ...);
315
// Store these here to allow access to the list without
316
// needing to have a wxMemStruct object.
317
static wxMemStruct* m_head;
318
static wxMemStruct* m_tail;
320
// Set to false if we're not checking all previous nodes when
321
// we do a new. Set to true when we are.
322
static bool m_checkPrevious;
325
// Final cleanup (e.g. deleting the log object and doing memory leak checking)
326
// will be delayed until all wxDebugContextDumpDelayCounter objects have been
327
// destructed. Adding one wxDebugContextDumpDelayCounter per file will delay
328
// memory leak checking until after destructing all global objects.
329
class WXDLLIMPEXP_BASE wxDebugContextDumpDelayCounter
332
wxDebugContextDumpDelayCounter() {
336
~wxDebugContextDumpDelayCounter() {
338
if(!sm_count) DoDump();
345
// make leak dump after all globals have been destructed
346
static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_File;
347
#define WXDEBUG_DUMPDELAYCOUNTER \
348
static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_Extra;
350
// Output a debug message, in a system dependent fashion.
351
void WXDLLIMPEXP_BASE wxTrace(const wxChar *fmt ...) ATTRIBUTE_PRINTF_1;
352
void WXDLLIMPEXP_BASE wxTraceLevel(int level, const wxChar *fmt ...) ATTRIBUTE_PRINTF_2;
354
#define WXTRACE wxTrace
355
#define WXTRACELEVEL wxTraceLevel
357
#else // (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
359
#define WXDEBUG_DUMPDELAYCOUNTER
361
// Borland C++ Builder 6 seems to have troubles with inline functions (see bug
364
inline void wxTrace(const wxChar *WXUNUSED(fmt)) {}
365
inline void wxTraceLevel(int WXUNUSED(level), const wxChar *WXUNUSED(fmt)) {}
368
#define wxTraceLevel(l, fmt)
371
#define WXTRACE true ? (void)0 : wxTrace
372
#define WXTRACELEVEL true ? (void)0 : wxTraceLevel
374
#endif // (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT