1 // $Id: fixmem.cpp 1282 2006-06-09 09:46:49Z alex $
2 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE
3 ================================XARAHEADERSTART===========================
5 Xara LX, a vector drawing and manipulation program.
6 Copyright (C) 1993-2006 Xara Group Ltd.
7 Copyright on certain contributions may be held in joint with their
8 respective authors. See AUTHORS file for details.
10 LICENSE TO USE AND MODIFY SOFTWARE
11 ----------------------------------
13 This file is part of Xara LX.
15 Xara LX is free software; you can redistribute it and/or modify it
16 under the terms of the GNU General Public License version 2 as published
17 by the Free Software Foundation.
19 Xara LX and its component source files are distributed in the hope
20 that it will be useful, but WITHOUT ANY WARRANTY; without even the
21 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 See the GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License along
25 with Xara LX (see the file GPL in the root directory of the
26 distribution); if not, write to the Free Software Foundation, Inc., 51
27 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 Conditional upon your continuing compliance with the GNU General Public
34 License described above, Xara Group Ltd grants to you certain additional
37 The additional rights are to use, modify, and distribute the software
38 together with the wxWidgets library, the wxXtra library, and the "CDraw"
39 library and any other such library that any version of Xara LX relased
40 by Xara Group Ltd requires in order to compile and execute, including
41 the static linking of that library to XaraLX. In the case of the
42 "CDraw" library, you may satisfy obligation under the GNU General Public
43 License to provide source code by providing a binary copy of the library
44 concerned and a copy of the license accompanying it.
46 Nothing in this section restricts any of the rights you have under
47 the GNU General Public License.
53 This license applies to this program (XaraLX) and its constituent source
54 files only, and does not necessarily apply to other Xara products which may
55 in part share the same code base, and are subject to their own licensing
58 This license does not apply to files in the wxXtra directory, which
59 are built into a separate library, and are subject to the wxWindows
60 license contained within that directory in the file "WXXTRA-LICENSE".
62 This license does not apply to the binary libraries (if any) within
63 the "libs" directory, which are subject to a separate license contained
64 within that directory in the file "LIBS-LICENSE".
67 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS
68 ----------------------------------------------
70 Subject to the terms of the GNU Public License (see above), you are
71 free to do whatever you like with your modifications. However, you may
72 (at your option) wish contribute them to Xara's source tree. You can
73 find details of how to do this at:
74 http://www.xaraxtreme.org/developers/
76 Prior to contributing your modifications, you will need to complete our
77 contributor agreement. This can be found at:
78 http://www.xaraxtreme.org/developers/contribute/
80 Please note that Xara will not accept modifications which modify any of
81 the text between the start and end of this header (marked
82 XARAHEADERSTART and XARAHEADEREND).
88 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara
89 designs are registered or unregistered trademarks, design-marks, and/or
90 service marks of Xara Group Ltd. All rights in these marks are reserved.
93 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK.
96 =================================XARAHEADEREND============================
99 // fixed memory allocator (used in preference to malloc/free etc)
102 #include "camtypes.h"
103 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED]
104 #if !defined(__WXMAC__)
107 #include <malloc/malloc.h>
109 //#include "ensure.h" - in camtypes.h [AUTOMATICALLY REMOVED]
110 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED]
112 #if !defined(EXCLUDE_FROM_XARLIB)
116 #if defined( __WXMSW__ )
118 #elif defined( __WXMAC__ )
122 //#include "ralphcri.h" // for critical sections
125 #if !defined(EXCLUDE_FROM_XARLIB)
126 static TunedMemory TheTunedMemoryManager
;
129 // Happy chappie critical crappy (for ralphm, threads and so forth)
130 CRITICAL_SECTION
CCMallocCriticalSection::sm_Section
;
131 BOOL
CCMallocCriticalSection::sm_bInit
= FALSE
;
133 #define checksize(x) FALSE
137 typedef struct CCMallocList
148 static CCMallocList
*TraceListHead
= NULL
;
151 #define MAGIC_LONGWORD 0xDEADBEEF
152 #define MAGIC_EXTRA sizeof(CCMallocList)
156 static INT32 TotalMalloced
= 0;
159 /********************************************************************************************
161 static void *CheckMagic( void* Block, BOOL Destroy )
163 Author: Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
165 Inputs: Block - pointer to memory block. If Destroy is TRUE will remove magic
166 marker so detect double-freeing.
168 Returns: Pointer before magic in block. Returns NULL if Block was null on input, or
169 if the block is not recognised as one of ours.
170 Purpose: For debug builds to ensure the magic longword marker is in the block.
171 If Destroy is TRUE then removes block from memory tracing list.
172 Stubbed away in retail builds.
173 Scope: Static to fixmem.cpp
175 ********************************************************************************************/
177 static void *CheckMagic( void* Block
, BOOL Destroy
)
181 CCMallocList
*p
= (CCMallocList
*)Block
;
183 // decrement pointer by sizeof(CCMallocList)
186 if ( p
->GuardWord
== MAGIC_LONGWORD
)
190 p
->GuardWord
= 0xF000BAAA; // if it was our marker then destroy it
192 if (p
== TraceListHead
)
193 TraceListHead
= p
->Next
;
196 p
->Next
->Prev
= p
->Prev
;
199 p
->Prev
->Next
= p
->Next
;
204 // if marker not there then either we didn't alloc it, or it has been freed for
206 ENSURE (FALSE
, "CCFree/realloc called on memory that was not CCMalloced");
207 return NULL
; // so no-one tries to use it
209 Block
= p
; // use real address to free
214 /********************************************************************************************
216 static void *StoreMagic( void *Block , UINT32 Size , LPCSTR Filename , INT32 Line )
218 Author: Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com> (and Gerry)
220 Inputs: Block - pointer to memory block. Stores magic longword in there.
222 Returns: The address just past that to the caller for use by the user.
223 Purpose: For debug builds to insert magic longword marker and other memory tracing
224 info in the block. Stubbed away in retail builds.
225 Scope: Static to fixmem.cpp
227 ********************************************************************************************/
229 static void *StoreMagic( void *Block
, size_t Size
, LPCSTR Filename
, INT32 Line
)
233 CCMallocList
*p
= (CCMallocList
*)Block
;
234 p
->GuardWord
= MAGIC_LONGWORD
; // store magic
238 // Fill in the details about the file position
239 if (Filename
!= NULL
)
241 // copy the string passed in and note the line number
242 size_t Count
= strlen( Filename
);
245 // The string was too long, so we have to copy just the last 22 chars in it
246 Filename
+= Count
-21;
249 // copy the end of the string into the space I have for it
250 strcpy( p
->Filename
, Filename
);
255 // set the fields to null values
256 strcpy( p
->Filename
, "Unknown File" ); // Was a IDS const, but too much effort for debug
260 p
->Start
= ((char*)Block
) + MAGIC_EXTRA
; // and return user bigger pointer
268 /********************************************************************************************
270 static void LinkMagic( void *Block )
272 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
274 Inputs: Block - pointer to memory block.
276 Purpose: For debug builds to link the block into the tracking list. Stubbed away in
278 Scope: Static to fixmem.cpp
280 ********************************************************************************************/
282 static void LinkMagic( void *Block
)
286 CCMallocList
*p
= (CCMallocList
*)Block
;
288 p
->GuardWord
= MAGIC_LONGWORD
; // store magic word
290 p
->Next
= TraceListHead
;
293 if (TraceListHead
!= NULL
)
294 TraceListHead
->Prev
= p
;
301 /********************************************************************************************
303 > void DumpCCMallocTrace(void)
305 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
310 Purpose: Lists any unreleased memory blocks
312 SeeAlso: LinkMagic;CheckMagic;StoreMagic
314 ********************************************************************************************/
316 void DumpCCMallocTrace(void)
318 if (TraceListHead
!= NULL
)
320 TRACE( _T("\n\n...CCMalloc leaks detected...\n\n"));
322 CCMallocList
*Ptr
= TraceListHead
;
326 #if 0 != wxUSE_UNICODE
328 camMbstowcs(pFilename
, Ptr
->Filename
, 22);
330 TCHAR
* pFilename
= Ptr
->Filename
;
332 TRACE( _T("%ld bytes allocated in %s at line %ld\n"),Ptr
->Size
, pFilename
, Ptr
->LineNum
);
336 TRACE( _T("\n...End of CCMalloc leaks...\n\n"));
341 /********************************************************************************************
343 > LPVOID DebugCCMalloc(UINT32 size, LPCSTR Filename, INT32 Line)
345 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
347 Inputs: size of block required
348 source filename called from (supplied by macro)
349 line number of call (supplied by macro)
352 Purpose: A version of malloc which does not throw exceptions and provides source file
353 and line number tracing.
354 Errors: Out of memory
355 SeeAlso: RetailCCMalloc;malloc
357 ********************************************************************************************/
359 LPVOID
DebugCCMalloc(size_t Size
, LPCSTR Filename
, INT32 Line
)
362 CCMallocCriticalSection Cs
;
365 if (Size
==0L) // size of 0 is illegal
367 ENSURE(FALSE
, "Someone asked for 0 bytes");
372 TotalMalloced
+= Size
;
373 TRACE( _T("Malloced %ld (+%ld in %s at line %ld)\n"),TotalMalloced
,Size
, Filename
, Line
);
376 size_t NewSize
= Size
+ MAGIC_EXTRA
;
378 if (checksize(NewSize
))
379 return NULL
; // if too big
381 // save VC++s internal fail-memory pointer and reset it so nothing special occurs
382 // if memory runs out
383 #if !defined(__WXMAC__)
384 _PNH old_handler
= _set_new_handler( NULL
);
386 new_handler pnh
= set_new_handler(NULL
);
389 // call malloc to get the memory or a NULL pointer
390 void *p
= malloc( (size_t)NewSize
);
392 // The next line is for debug purposes (comment out above line)
395 // repair the function pointer to its old value and return our pointer
396 #if !defined(__WXMAC__)
397 _set_new_handler( old_handler
);
399 set_new_handler(pnh
);
402 // set the error and return if it didn't work
405 Error::SetError(_R(IDS_OUT_OF_MEMORY
));
409 // Link block in to list
412 // TRACE( _T("CCMalloc at 0x%08x (0x%08x)\n"), (char*)p + MAGIC_EXTRA, p);
414 // add the magic longword
415 return StoreMagic(p
, Size
, Filename
, Line
);
419 /********************************************************************************************
421 void DebugCCRealloc(LPVOID Buf, UINT32 Size, LPCSTR Filename, INT32 Line)
423 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
425 Inputs: pointer to memory allocated with CCMalloc (or NULL)
427 source filename called from (supplied by macro)
428 line number of call (supplied by macro)
431 Purpose: A version of realloc which does not throw exceptions and provides source file
432 and line number tracing. DO NOT CALL. Use CCRealloc instead.
433 Errors: Out of memory
434 SeeAlso: RetailCCRealloc;realloc
436 ********************************************************************************************/
438 LPVOID
DebugCCRealloc(LPVOID Buf
, size_t Size
, LPCSTR Filename
, INT32 Line
)
441 CCMallocCriticalSection Cs
;
444 if (Size
==0L) // size of 0 is illegal
446 ENSURE(FALSE
, "Someone asked for 0 bytes");
450 // check magic longword (and remove it)
451 const LPVOID NewBuf
= CheckMagic(Buf
, TRUE
); // Unlink block and set deleted
457 // CheckMagic decided that it wasn't one of our blocks, so don't try to grow it
461 size_t NewSize
= Size
+ MAGIC_EXTRA
;
463 if (checksize(NewSize
))
464 return NULL
; // if too big
466 // save VC++s internal fail-memory pointer and reset it so nothing special occurs
467 // if memory runs out
468 #if !defined(__WXMAC__)
469 _PNH old_handler
= _set_new_handler( NULL
);
471 new_handler pnh
= set_new_handler(NULL
);
475 void *p
= realloc( NewBuf
, (size_t)NewSize
);
477 // The next line is for test purposes (comment out above line)
480 // finally repair the function pointer to its old value and return our pointer
481 #if !defined(__WXMAC__)
482 _set_new_handler( old_handler
);
484 set_new_handler(pnh
);
487 // set the error and return if it didn't work
490 Error::SetError(_R(IDS_OUT_OF_MEMORY
));
492 // Re-link old block into list
495 // return NULL as realloc
500 // TRACE( _T("CCRealloc at 0x%08x (0x%08x) is now 0x%08x (0x%08x)\n"), Buf, NewBuf, (char*)p+MAGIC_EXTRA, p);
502 // Link new block into list
505 // return result, storing magic word
506 return StoreMagic(p
, Size
, Filename
, Line
);
512 /********************************************************************************************
514 > INT32 DebugCCGetBlockSize(LPVOID Block)
516 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
518 Inputs: Block - the alloc'ed block we want to know the size of
519 Returns: the size of the block that was asked for
520 Purpose: Finds out how big a block of ram someone asked for when they called CCMalloc
522 ********************************************************************************************/
524 size_t DebugCCGetBlockSize(LPVOID Block
)
529 // make sure it is OK
533 CCMallocList
*p
= (CCMallocList
*) (((char*)Block
)-MAGIC_EXTRA
);
543 // retail builds stub out those fns just in case
544 // the only one that is used is CheckMagic (in CCFree)
545 #define CheckMagic(p,k) (p)
546 #define StoreMagic(p,s,f,l) (p)
548 #define MAGIC_EXTRA 0
550 /********************************************************************************************
552 LPVOID RetailCCMalloc( UINT32 size )
554 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
556 Inputs: size of memory required (must be non-zero)
558 Returns: Pointer to new block, or NULL if failed.
559 Purpose: Like malloc but does not throw exceptions.
561 SeeAlso: CCFree;RetailCCRealloc;malloc
563 ********************************************************************************************/
565 LPVOID
RetailCCMalloc( UINT32 Size
)
568 CCMallocCriticalSection Cs
;
571 if (Size
==0L) // size of 0 is illegal
575 return NULL
; // if too big
577 // save VC++s internal fail-memory pointer and reset it so nothing special occurs
578 // if memory runs out
579 #if !defined(__WXMAC__)
580 _PNH old_handler
= _set_new_handler( NULL
);
582 new_handler pnh
= set_new_handler(NULL
);
585 // call malloc to get the memory or a NULL pointer
586 void *p
= malloc( (size_t)Size
);
588 // repair the function pointer to its old value and return our pointer
589 #if !defined(__WXMAC__)
590 _set_new_handler( old_handler
);
592 set_new_handler(pnh
);
595 // set the error if it didn't work
597 Error::SetError(_R(IDS_OUT_OF_MEMORY
));
605 /********************************************************************************************
607 LPVOID RetailCCRealloc( LPVOID buf, UINT32 size )
609 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
611 Inputs: Pointer to block allocated with CCMalloc (can be NULL) and new size (must be non-zero)
612 Returns: Pointer to new block (might have changed) or NULL if cannot reallocate (old block
614 Purpose: Change size of memory block, similar to realloc but does not throw exceptions.
616 SeeAlso: RetailCCMalloc;CCFree;realloc
618 ********************************************************************************************/
620 LPVOID
RetailCCRealloc( LPVOID Buf
, UINT32 Size
)
623 CCMallocCriticalSection Cs
;
626 if (Size
==0L) // size of 0 is illegal
630 return NULL
; // if too big
632 // save VC++s internal fail-memory pointer and reset it so nothing special occurs
633 // if memory runs out
634 #if !defined(__WXMAC__)
635 _PNH old_handler
= _set_new_handler( NULL
);
637 new_handler pnh
= set_new_handler(NULL
);
641 void *p
= realloc( Buf
, (size_t)Size
);
643 // finally repair the function pointer to its old value and return our pointer
644 #if !defined(__WXMAC__)
645 _set_new_handler( old_handler
);
647 set_new_handler(pnh
);
650 // set the error if it didn't work
652 Error::SetError(_R(IDS_OUT_OF_MEMORY
));
654 // return result, storing magic word
661 /********************************************************************************************
663 > size_t RetailCCGetBlockSize(LPVOID Block)
665 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
667 Inputs: Block - the alloc'ed block we want to know the size of
668 Returns: the size of the block that was asked for
669 Purpose: Finds out how big a block of ram someone asked for when they called CCMalloc
671 ********************************************************************************************/
673 size_t RetailCCGetBlockSize(LPVOID Block
)
676 CCMallocCriticalSection Cs
;
682 #if !defined(__WXMAC__)
683 return _msize(Block
);
685 return malloc_size(Block
);
694 /********************************************************************************************
696 > LPVOID CCMalloc( UINT32 size )
698 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
700 Inputs: size of memory required (must be non-zero)
702 Returns: Pointer to new block, or NULL if failed.
703 Purpose: Like malloc but does not throw exceptions.
705 SeeAlso: malloc;CCFree;CCRealloc
707 ********************************************************************************************/
710 This has been implemented as a macro which calls either RetailCCMalloc or DebugCCMalloc
711 depending on whether it is a retail or debug build.
713 ********************************************************************************************/
716 /********************************************************************************************
718 > LPVOID CCRealloc( LPVOID buf, UINT32 size )
720 Author: Gerry_Iles (Xara Group Ltd) <camelotdev@xara.com>
722 Inputs: Pointer to block allocated with CCMalloc (can be NULL) and new size (must be non-zero)
723 Returns: Pointer to new block (might have changed) or NULL if cannot reallocate (old block
725 Purpose: Change size of memory block, similar to realloc but does not throw exceptions.
727 SeeAlso: RetailCCMalloc;CCFree;realloc
729 ********************************************************************************************/
732 This has been implemented as a macro which calls either RetailCCRealloc or DebugCCRealloc
733 depending on whether it is a retail or debug build.
735 ********************************************************************************************/
738 /********************************************************************************************
740 > void CCFree( LPBYTE buf )
742 Author: Andy_Pennell (Xara Group Ltd) <camelotdev@xara.com>
744 Inputs: pointer to memory allocated with CCMalloc (or NULL)
749 SeeAlso: CCMalloc;free
751 ********************************************************************************************/
753 void CCFree( LPVOID Buf
)
756 CCMallocCriticalSection Cs
;
762 CCMallocList
* p
= (CCMallocList
*) Buf
;
764 TotalMalloced
-= p
->Size
;
765 TRACE( _T("UnMalloced %ld (-%ld in %s at %ld)\n"),TotalMalloced
, p
->Size
, p
->Filename
, p
->LineNum
);
769 // check magic longword (and remove it to find double-frees)
770 Buf
= CheckMagic( Buf
, TRUE
);
772 // TRACE( _T("CCFree at 0x%08x (0x%08x)\n"), Buf, ((char*)Buf - MAGIC_EXTRA));
781 #if !defined(EXCLUDE_FROM_XARLIB)
782 /********************************************************************************************
784 > TunedMemory* GetTunedMemManager()
786 Author: Rik_Heywood (Xara Group Ltd) <camelotdev@xara.com>
788 Returns: A pointer to the tuned memory manager
789 Purpose: Finds the Tuned Memory manager so that people that need to know get ask
792 ********************************************************************************************/
794 TunedMemory
* GetTunedMemManager()
796 return &TheTunedMemoryManager
;