]> git.saurik.com Git - wxWidgets.git/blob - include/wx/memory.h
Fixed #12566 (assert on deletion) due to inconsistent commit
[wxWidgets.git] / include / wx / memory.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/memory.h
3 // Purpose: Memory operations
4 // Author: Arthur Seaton, Julian Smart
5 // Modified by:
6 // Created: 29/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_MEMORY_H_
13 #define _WX_MEMORY_H_
14
15 #include "wx/defs.h"
16 #include "wx/string.h"
17 #include "wx/msgout.h"
18
19 #if wxUSE_MEMORY_TRACING || wxUSE_DEBUG_CONTEXT
20
21 #include <stddef.h>
22
23 WXDLLIMPEXP_BASE void * wxDebugAlloc(size_t size, wxChar * fileName, int lineNum, bool isObject, bool isVect = false);
24 WXDLLIMPEXP_BASE void wxDebugFree(void * buf, bool isVect = false);
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.
34
35
36 #if wxUSE_GLOBAL_MEMORY_OPERATORS
37
38 // Undefine temporarily (new is #defined in object.h) because we want to
39 // declare some new operators.
40 #ifdef new
41 #undef new
42 #endif
43
44 #if defined(__SUNCC__)
45 #define wxUSE_ARRAY_MEMORY_OPERATORS 0
46 #elif !( defined (__VISUALC__) && (__VISUALC__ <= 1020) ) || defined( __MWERKS__)
47 #define wxUSE_ARRAY_MEMORY_OPERATORS 1
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
53 #elif !( defined (__VISUALC__) && (__VISUALC__ <= 1020) ) || defined( __MWERKS__)
54 #define wxUSE_ARRAY_MEMORY_OPERATORS 1
55 #else
56 // ::operator new[] is a recent C++ feature, so assume it's not supported
57 #define wxUSE_ARRAY_MEMORY_OPERATORS 0
58 #endif
59
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))
64 inline void * operator new (size_t size, wxChar * fileName, int lineNum)
65 {
66 return wxDebugAlloc(size, fileName, lineNum, false, false);
67 }
68
69 inline void * operator new (size_t size)
70 {
71 return wxDebugAlloc(size, NULL, 0, false);
72 }
73
74 inline void operator delete (void * buf)
75 {
76 wxDebugFree(buf, false);
77 }
78
79 #if wxUSE_ARRAY_MEMORY_OPERATORS
80 inline void * operator new[] (size_t size)
81 {
82 return wxDebugAlloc(size, NULL, 0, false, true);
83 }
84
85 inline void * operator new[] (size_t size, wxChar * fileName, int lineNum)
86 {
87 return wxDebugAlloc(size, fileName, lineNum, false, true);
88 }
89
90 inline void operator delete[] (void * buf)
91 {
92 wxDebugFree(buf, true);
93 }
94 #endif // wxUSE_ARRAY_MEMORY_OPERATORS
95
96 #else
97
98 void * operator new (size_t size, wxChar * fileName, int lineNum);
99
100 void * operator new (size_t size);
101
102 void operator delete (void * buf);
103
104 #if wxUSE_ARRAY_MEMORY_OPERATORS
105 void * operator new[] (size_t size);
106
107 void * operator new[] (size_t size, wxChar * fileName, int lineNum);
108
109 void operator delete[] (void * buf);
110 #endif // wxUSE_ARRAY_MEMORY_OPERATORS
111 #endif // defined(__WXMSW__) && (defined(WXUSINGDLL) || defined(WXMAKINGDLL_BASE))
112
113 // VC++ 6.0 and MWERKS
114 #if ( defined(__VISUALC__) && (__VISUALC__ >= 1200) ) || defined(__MWERKS__)
115 inline void operator delete(void* pData, wxChar* /* fileName */, int /* lineNum */)
116 {
117 wxDebugFree(pData, false);
118 }
119 inline void operator delete[](void* pData, wxChar* /* fileName */, int /* lineNum */)
120 {
121 wxDebugFree(pData, true);
122 }
123 #endif // __VISUALC__>=1200
124 #endif // wxUSE_GLOBAL_MEMORY_OPERATORS
125
126 //**********************************************************************************
127
128 typedef unsigned int wxMarkerType;
129
130 /*
131 Define the struct which will be placed at the start of all dynamically
132 allocated memory.
133 */
134
135 class WXDLLIMPEXP_BASE wxMemStruct {
136
137 friend class WXDLLIMPEXP_FWD_BASE wxDebugContext; // access to the m_next pointer for list traversal.
138
139 public:
140 public:
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
175 public:
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.
181 wxChar* m_fileName;
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
200 typedef void (wxMemStruct::*PmSFV) ();
201
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).
204 typedef void (*wxShutdownNotifyFunction)();
205
206 /*
207 Debugging class. This will only have a single instance, but it's
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
211 it's stuff which we need to access at times when there is no wxMemStruct
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
216 class WXDLLIMPEXP_BASE wxDebugContext {
217
218 protected:
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
230 static int debugLevel;
231 static bool debugOn;
232
233 static int m_balign; // byte alignment
234 static int m_balignmask; // mask for performing byte alignment
235 public:
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
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
249 static void SetCheckpoint(bool all = false);
250 static wxMemStruct *GetCheckpoint(void) { return checkPoint; }
251
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
283 // Checks all nodes, or all nodes if checkAll is true
284 static int Check(bool checkAll = false);
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
293 static bool PrintStatistics(bool detailed = true);
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
300 static int CountObjectsLeft(bool sinceCheckpoint = false);
301
302 // This function is used to output the dump
303 static void OutputDumpLine(const wxChar *szFormat, ...);
304
305 static void SetShutdownNotifyFunction(wxShutdownNotifyFunction shutdownFn);
306
307 private:
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
313 // Set to false if we're not checking all previous nodes when
314 // we do a new. Set to true when we are.
315 static bool m_checkPrevious;
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;
322 };
323
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.
328
329 class WXDLLIMPEXP_BASE wxDebugContextDumpDelayCounter
330 {
331 public:
332 wxDebugContextDumpDelayCounter();
333 ~wxDebugContextDumpDelayCounter();
334
335 private:
336 void DoDump();
337 static int sm_count;
338 };
339
340 // make leak dump after all globals have been destructed
341 static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_File;
342 #define WXDEBUG_DUMPDELAYCOUNTER \
343 static wxDebugContextDumpDelayCounter wxDebugContextDumpDelayCounter_Extra;
344
345 // Output a debug message, in a system dependent fashion.
346 void WXDLLIMPEXP_BASE wxTrace(const wxChar *fmt ...) WX_ATTRIBUTE_PRINTF_1;
347 void WXDLLIMPEXP_BASE wxTraceLevel(int level, const wxChar *fmt ...) WX_ATTRIBUTE_PRINTF_2;
348
349 #define WXTRACE wxTrace
350 #define WXTRACELEVEL wxTraceLevel
351
352 #else // wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
353
354 #define WXDEBUG_DUMPDELAYCOUNTER
355
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
365
366 #define WXTRACE true ? (void)0 : wxTrace
367 #define WXTRACELEVEL true ? (void)0 : wxTraceLevel
368
369 #endif // wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT
370
371 #endif // _WX_MEMORY_H_