]> git.saurik.com Git - wxWidgets.git/blame - include/wx/memory.h
look for backtrace() in -lexecinfo, fixes #9783
[wxWidgets.git] / include / wx / memory.h
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
5b56bffb
WS
2// Name: wx/memory.h
3// Purpose: Memory operations
c801d85f
KB
4// Author: Arthur Seaton, Julian Smart
5// Modified by:
6// Created: 29/01/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Julian Smart
65571936 9// Licence: wxWindows licence
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
657a8a35
VZ
12#ifndef _WX_MEMORY_H_
13#define _WX_MEMORY_H_
c801d85f 14
c801d85f 15#include "wx/defs.h"
2432b92d 16#include "wx/string.h"
ced55544 17#include "wx/msgout.h"
c801d85f 18
657a8a35 19#if wxUSE_MEMORY_TRACING || wxUSE_DEBUG_CONTEXT
c801d85f
KB
20
21#include <stddef.h>
22
4e32eea1
WS
23WXDLLIMPEXP_BASE void * wxDebugAlloc(size_t size, wxChar * fileName, int lineNum, bool isObject, bool isVect = false);
24WXDLLIMPEXP_BASE void wxDebugFree(void * buf, bool isVect = false);
2db0bbde
JS
25
26//**********************************************************************************
27/*
28 The global operator new used for everything apart from getting
29 dynamic storage within this function itself.
30*/
31
32// We'll only do malloc and free for the moment: leave the interesting
33// stuff for the wxObject versions.
241421a6 34
c801d85f 35
47d67540 36#if wxUSE_GLOBAL_MEMORY_OPERATORS
c801d85f 37
6b037754
JS
38// Undefine temporarily (new is #defined in object.h) because we want to
39// declare some new operators.
c801d85f 40#ifdef new
3f4a0c5b 41 #undef new
c801d85f
KB
42#endif
43
5dcf05ae 44#if defined(__SUNCC__)
3f4a0c5b
VZ
45 #define wxUSE_ARRAY_MEMORY_OPERATORS 0
46#elif !( defined (__VISUALC__) && (__VISUALC__ <= 1020) ) || defined( __MWERKS__)
47 #define wxUSE_ARRAY_MEMORY_OPERATORS 1
ba6f401d
VZ
48#elif defined (__SGI_CC_)
49 // only supported by -n32 compilers
50 #ifndef __EDG_ABI_COMPATIBILITY_VERSION
51 #define wxUSE_ARRAY_MEMORY_OPERATORS 0
52 #endif
2db0bbde
JS
53#elif !( defined (__VISUALC__) && (__VISUALC__ <= 1020) ) || defined( __MWERKS__)
54 #define wxUSE_ARRAY_MEMORY_OPERATORS 1
5dcf05ae 55#else
ba6f401d 56 // ::operator new[] is a recent C++ feature, so assume it's not supported
3f4a0c5b 57 #define wxUSE_ARRAY_MEMORY_OPERATORS 0
5dcf05ae
JS
58#endif
59
241421a6
JS
60// devik 2000-8-29: All new/delete ops are now inline because they can't
61// be marked as dllexport/dllimport. It then leads to weird bugs when
62// used on MSW as DLL
63#if defined(__WXMSW__) && (defined(WXUSINGDLL) || defined(WXMAKINGDLL_BASE))
64inline void * operator new (size_t size, wxChar * fileName, int lineNum)
65{
5b56bffb 66 return wxDebugAlloc(size, fileName, lineNum, false, false);
241421a6
JS
67}
68
69inline void * operator new (size_t size)
70{
5b56bffb 71 return wxDebugAlloc(size, NULL, 0, false);
241421a6
JS
72}
73
74inline void operator delete (void * buf)
75{
5b56bffb 76 wxDebugFree(buf, false);
241421a6
JS
77}
78
79#if wxUSE_ARRAY_MEMORY_OPERATORS
80inline void * operator new[] (size_t size)
81{
5b56bffb 82 return wxDebugAlloc(size, NULL, 0, false, true);
241421a6
JS
83}
84
85inline void * operator new[] (size_t size, wxChar * fileName, int lineNum)
86{
5b56bffb 87 return wxDebugAlloc(size, fileName, lineNum, false, true);
241421a6
JS
88}
89
90inline void operator delete[] (void * buf)
91{
5b56bffb 92 wxDebugFree(buf, true);
241421a6
JS
93}
94#endif // wxUSE_ARRAY_MEMORY_OPERATORS
95
96#else
97
aaf1bbfd 98void * operator new (size_t size, wxChar * fileName, int lineNum);
b40b0f5b 99
aaf1bbfd 100void * operator new (size_t size);
2db0bbde 101
aaf1bbfd 102void operator delete (void * buf);
c801d85f 103
5dcf05ae 104#if wxUSE_ARRAY_MEMORY_OPERATORS
aaf1bbfd
JS
105void * operator new[] (size_t size);
106
107void * operator new[] (size_t size, wxChar * fileName, int lineNum);
108
109void operator delete[] (void * buf);
241421a6
JS
110#endif // wxUSE_ARRAY_MEMORY_OPERATORS
111#endif // defined(__WXMSW__) && (defined(WXUSINGDLL) || defined(WXMAKINGDLL_BASE))
c801d85f 112
ba14d986
VZ
113// VC++ 6.0 and MWERKS
114#if ( defined(__VISUALC__) && (__VISUALC__ >= 1200) ) || defined(__MWERKS__)
2db0bbde
JS
115inline void operator delete(void* pData, wxChar* /* fileName */, int /* lineNum */)
116{
4e32eea1 117 wxDebugFree(pData, false);
2db0bbde
JS
118}
119inline void operator delete[](void* pData, wxChar* /* fileName */, int /* lineNum */)
120{
4e32eea1 121 wxDebugFree(pData, true);
2db0bbde
JS
122}
123#endif // __VISUALC__>=1200
124#endif // wxUSE_GLOBAL_MEMORY_OPERATORS
2db0bbde
JS
125
126//**********************************************************************************
c801d85f
KB
127
128typedef unsigned int wxMarkerType;
129
130/*
131 Define the struct which will be placed at the start of all dynamically
132 allocated memory.
133*/
134
bddd7a8d 135class WXDLLIMPEXP_BASE wxMemStruct {
c801d85f 136
b5dbe15d 137friend class WXDLLIMPEXP_FWD_BASE wxDebugContext; // access to the m_next pointer for list traversal.
c801d85f
KB
138
139public:
140public:
141 int AssertList ();
142
143 size_t RequestSize () { return m_reqSize; }
144 wxMarkerType Marker () { return m_firstMarker; }
145
146 // When an object is deleted we set the id slot to a specific value.
147 inline void SetDeleted ();
148 inline int IsDeleted ();
149
150 int Append ();
151 int Unlink ();
152
153 // Used to determine if the object is really a wxMemStruct.
154 // Not a foolproof test by any means, but better than none I hope!
155 int AssertIt ();
156
157 // Do all validation on a node.
158 int ValidateNode ();
159
160 // Check the integrity of a node and of the list, node by node.
161 int CheckBlock ();
162 int CheckAllPrevious ();
163
164 // Print a single node.
165 void PrintNode ();
166
167 // Called when the memory linking functions get an error.
168 void ErrorMsg (const char *);
169 void ErrorMsg ();
170
171 inline void *GetActualData(void) const { return m_actualData; }
172
173 void Dump(void);
174
175public:
176 // Check for underwriting. There are 2 of these checks. This one
177 // inside the struct and another right after the struct.
178 wxMarkerType m_firstMarker;
179
180 // File name and line number are from cpp.
4de6207a 181 wxChar* m_fileName;
c801d85f
KB
182 int m_lineNum;
183
184 // The amount of memory requested by the caller.
185 size_t m_reqSize;
186
187 // Used to try to verify that we really are dealing with an object
188 // of the required class. Can be 1 of 2 values these indicating a valid
189 // wxMemStruct object, or a deleted wxMemStruct object.
190 wxMarkerType m_id;
191
192 wxMemStruct * m_prev;
193 wxMemStruct * m_next;
194
195 void * m_actualData;
196 bool m_isObject;
197};
198
199
200typedef void (wxMemStruct::*PmSFV) ();
201
6dfbea27
VZ
202// Type of the app function that can be installed and called at wxWidgets shutdown
203// (after all other registered files with global destructors have been closed down).
204typedef void (*wxShutdownNotifyFunction)();
c801d85f
KB
205
206/*
b073db94 207 Debugging class. This will only have a single instance, but it's
c801d85f
KB
208 a reasonable way to keep everything together and to make this
209 available for change if needed by someone else.
210 A lot of this stuff would be better off within the wxMemStruct class, but
b073db94 211 it's stuff which we need to access at times when there is no wxMemStruct
c801d85f
KB
212 object so we use this class instead. Think of it as a collection of
213 globals which have to do with the wxMemStruct class.
214*/
215
bddd7a8d 216class WXDLLIMPEXP_BASE wxDebugContext {
c801d85f
KB
217
218protected:
219 // Used to set alignment for markers.
220 static size_t CalcAlignment ();
221
222 // Returns the amount of padding needed after something of the given
223 // size. This is so that when we cast pointers backwards and forwards
224 // the pointer value will be valid for a wxMarkerType.
225 static size_t GetPadding (const size_t size) ;
226
227 // Traverse the list.
228 static void TraverseList (PmSFV, wxMemStruct *from = NULL);
229
c801d85f
KB
230 static int debugLevel;
231 static bool debugOn;
232
478e6b71
VZ
233 static int m_balign; // byte alignment
234 static int m_balignmask; // mask for performing byte alignment
c801d85f
KB
235public:
236 // Set a checkpoint to dump only the memory from
237 // a given point
238 static wxMemStruct *checkPoint;
239
240 wxDebugContext(void);
241 ~wxDebugContext(void);
242
c801d85f
KB
243 static int GetLevel(void) { return debugLevel; }
244 static void SetLevel(int level) { debugLevel = level; }
245
246 static bool GetDebugMode(void) { return debugOn; }
247 static void SetDebugMode(bool flag) { debugOn = flag; }
248
4e32eea1 249 static void SetCheckpoint(bool all = false);
c801d85f 250 static wxMemStruct *GetCheckpoint(void) { return checkPoint; }
2bd5bbc9 251
c801d85f
KB
252 // Calculated from the request size and any padding needed
253 // before the final marker.
254 static size_t PaddedSize (const size_t reqSize);
255
256 // Calc the total amount of space we need from the system
257 // to satisfy a caller request. This includes all padding.
258 static size_t TotSize (const size_t reqSize);
259
260 // Return valid pointers to offsets within the allocated memory.
261 static char * StructPos (const char * buf);
262 static char * MidMarkerPos (const char * buf);
263 static char * CallerMemPos (const char * buf);
264 static char * EndMarkerPos (const char * buf, const size_t size);
265
266 // Given a pointer to the start of the caller requested area
267 // return a pointer to the start of the entire alloc\'d buffer.
268 static char * StartPos (const char * caller);
269
270 // Access to the list.
271 static wxMemStruct * GetHead () { return m_head; }
272 static wxMemStruct * GetTail () { return m_tail; }
273
274 // Set the list sentinals.
275 static wxMemStruct * SetHead (wxMemStruct * st) { return (m_head = st); }
276 static wxMemStruct * SetTail (wxMemStruct * st) { return (m_tail = st); }
277
278 // If this is set then every new operation checks the validity
279 // of the all previous nodes in the list.
280 static bool GetCheckPrevious () { return m_checkPrevious; }
281 static void SetCheckPrevious (bool value) { m_checkPrevious = value; }
282
4e32eea1
WS
283 // Checks all nodes, or all nodes if checkAll is true
284 static int Check(bool checkAll = false);
c801d85f
KB
285
286 // Print out the list of wxMemStruct nodes.
287 static bool PrintList(void);
288
289 // Dump objects
290 static bool Dump(void);
291
292 // Print statistics
4e32eea1 293 static bool PrintStatistics(bool detailed = true);
c801d85f
KB
294
295 // Print out the classes in the application.
296 static bool PrintClasses(void);
297
298 // Count the number of non-wxDebugContext-related objects
299 // that are outstanding
4e32eea1 300 static int CountObjectsLeft(bool sinceCheckpoint = false);
c801d85f 301
ced55544
VS
302 // This function is used to output the dump
303 static void OutputDumpLine(const wxChar *szFormat, ...);
304
6dfbea27
VZ
305 static void SetShutdownNotifyFunction(wxShutdownNotifyFunction shutdownFn);
306
c801d85f
KB
307private:
308 // Store these here to allow access to the list without
309 // needing to have a wxMemStruct object.
310 static wxMemStruct* m_head;
311 static wxMemStruct* m_tail;
312
4e32eea1
WS
313 // Set to false if we're not checking all previous nodes when
314 // we do a new. Set to true when we are.
c801d85f 315 static bool m_checkPrevious;
6dfbea27
VZ
316
317 // Holds a pointer to an optional application function to call at shutdown.
318 static wxShutdownNotifyFunction sm_shutdownFn;
319
320 // Have to access our shutdown hook
321 friend class wxDebugContextDumpDelayCounter;
c801d85f
KB
322};
323
ced55544
VS
324// Final cleanup (e.g. deleting the log object and doing memory leak checking)
325// will be delayed until all wxDebugContextDumpDelayCounter objects have been
326// destructed. Adding one wxDebugContextDumpDelayCounter per file will delay
327// memory leak checking until after destructing all global objects.
6dfbea27 328
ced55544
VS
329class WXDLLIMPEXP_BASE wxDebugContextDumpDelayCounter
330{
331public:
6dfbea27
VZ
332 wxDebugContextDumpDelayCounter();
333 ~wxDebugContextDumpDelayCounter();
334
ced55544
VS
335private:
336 void DoDump();
337 static int sm_count;
338};
339
340// make leak dump after all globals have been destructed
341static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_File;
342#define WXDEBUG_DUMPDELAYCOUNTER \
343 static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_Extra;
344
6b037754 345// Output a debug message, in a system dependent fashion.
862bb5c7
VS
346void WXDLLIMPEXP_BASE wxTrace(const wxChar *fmt ...) WX_ATTRIBUTE_PRINTF_1;
347void WXDLLIMPEXP_BASE wxTraceLevel(int level, const wxChar *fmt ...) WX_ATTRIBUTE_PRINTF_2;
c801d85f
KB
348
349#define WXTRACE wxTrace
350#define WXTRACELEVEL wxTraceLevel
351
657a8a35 352#else // wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
ced55544
VS
353
354#define WXDEBUG_DUMPDELAYCOUNTER
c801d85f 355
f2e5c082
VZ
356// Borland C++ Builder 6 seems to have troubles with inline functions (see bug
357// 819700)
358#if 0
359 inline void wxTrace(const wxChar *WXUNUSED(fmt)) {}
360 inline void wxTraceLevel(int WXUNUSED(level), const wxChar *WXUNUSED(fmt)) {}
361#else
362 #define wxTrace(fmt)
363 #define wxTraceLevel(l, fmt)
364#endif
c801d85f 365
4e32eea1
WS
366#define WXTRACE true ? (void)0 : wxTrace
367#define WXTRACELEVEL true ? (void)0 : wxTraceLevel
c801d85f 368
657a8a35 369#endif // wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
c801d85f 370
657a8a35 371#endif // _WX_MEMORY_H_