0023279: Accessing NULL pointer
[occt.git] / src / Standard / Standard.cxx
CommitLineData
b311480e 1// Created on: 2005-03-15
2// Created by: Peter KURNEV
3// Copyright (c) 1998-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21
22
23#include <Standard.ixx>
24
25#include <stdlib.h>
26
27#include <Standard_MMgrOpt.hxx>
28#include <Standard_MMgrRaw.hxx>
29#include <Standard_MMgrTBBalloc.hxx>
30
af09dbff 31#if(defined(_WIN32) || defined(__WIN32__))
32#include <windows.h>
33#include <malloc.h>
34#endif
35
7fd59977 36// Global reentrant flag
af09dbff 37static Standard_Boolean Standard_IsReentrant = Standard_True;
7fd59977 38
39//=======================================================================
40//class : Standard_MMgrFactory
41//purpose : Container for pointer to memory manager;
42// used to construct appropriate memory manager according
43// to environment settings, and to ensure destruction upon exit
44//=======================================================================
45
46class Standard_MMgrFactory {
47 public:
48 Standard_MMgrFactory();
49 ~Standard_MMgrFactory();
50 public:
51 Standard_MMgrRoot* myFMMgr;
52};
53
54//=======================================================================
55//function : Standard_MMgrFactory
56//purpose : Check environment variables and create appropriate memory manager
57//=======================================================================
58
af09dbff 59Standard_MMgrFactory::Standard_MMgrFactory()
60: myFMMgr (NULL)
7fd59977 61{
af09dbff 62 char* aVar;
63 Standard_Integer anAllocId = (aVar = getenv ("MMGT_OPT" )) ? atoi (aVar) : 0;
64 Standard_Boolean toClear = (aVar = getenv ("MMGT_CLEAR" )) ? (atoi (aVar) != 0) : Standard_True;
65
66
67 // on Windows (actual for XP and 2000) activate low fragmentation heap
68 // for CRT heap in order to get best performance.
69 // Environment variable MMGT_LFH can be used to switch off this action (if set to 0)
70#if defined(_MSC_VER)
71 aVar = getenv ("MMGT_LFH");
72 if ( aVar == NULL || atoi (aVar) != 0 )
73 {
74 ULONG aHeapInfo = 2;
75 HANDLE aCRTHeap = (HANDLE)_get_heap_handle();
76 HeapSetInformation (aCRTHeap, HeapCompatibilityInformation, &aHeapInfo, sizeof(aHeapInfo));
7fd59977 77 }
af09dbff 78#endif
79
80 aVar = getenv ("MMGT_REENTRANT");
81 if ( aVar != NULL )
82 Standard_IsReentrant = (atoi (aVar) != 0);
7fd59977 83
af09dbff 84 switch (anAllocId)
85 {
86 case 1: // OCCT optimized memory allocator
87 {
88 Standard_Boolean bMMap = (aVar = getenv ("MMGT_MMAP" )) ? (atoi (aVar) != 0) : Standard_True;
89 Standard_Integer aCellSize = (aVar = getenv ("MMGT_CELLSIZE" )) ? atoi (aVar) : 200;
90 Standard_Integer aNbPages = (aVar = getenv ("MMGT_NBPAGES" )) ? atoi (aVar) : 1000;
91 Standard_Integer aThreshold = (aVar = getenv ("MMGT_THRESHOLD")) ? atoi (aVar) : 40000;
92 myFMMgr = new Standard_MMgrOpt (toClear, bMMap, aCellSize, aNbPages, aThreshold, Standard_IsReentrant);
93 break;
94 }
95 case 2: // TBB memory allocator
96 myFMMgr = new Standard_MMgrTBBalloc (toClear);
97 break;
98 case 0:
99 default: // system default memory allocator
100 myFMMgr = new Standard_MMgrRaw (toClear);
101 }
7fd59977 102}
103
104//=======================================================================
105//function : ~Standard_MMgrFactory
106//purpose :
107//=======================================================================
108
109Standard_MMgrFactory::~Standard_MMgrFactory()
110{
207e57e4 111 if ( myFMMgr ) {
7fd59977 112 myFMMgr->Purge(Standard_True);
113// delete myFMMgr;
114// myFMMgr = 0;
115 }
116}
117
118//=======================================================================
119// function: GetMMgr
120//
121// This static function has a purpose to wrap static holder for memory
122// manager instance.
123//
124// Wrapping holder inside a function is needed to ensure that it will
125// be initialized not later than the first call to memory manager (that
126// would be impossible to guarantee if holder was static variable on
127// global or file scope, because memory manager may be called from
128// constructors of other static objects).
129//
130// Note that at the same time we could not guarantee that the holder
131// object is destroyed after last call to memory manager, since that
132// last call may be from static Handle() object which has been initialized
133// dynamically during program execution rather than in its constructor.
134//
135// Therefore holder currently does not call destructor of the memory manager
136// but only its method Purge() with Standard_True.
137//
138// To free the memory completely, we probably could use compiler-specific
139// pragmas (such as '#pragma fini' on SUN Solaris and '#pragma init_seg' on
140// WNT MSVC++) to put destructing function in code segment that is called
141// after destructors of other (even static) objects. However, this is not
142// done by the moment since it is compiler-dependent and there is no guarantee
143// thatsome other object calling memory manager is not placed also in that segment...
144//
145// Note that C runtime function atexit() could not help in this problem
146// since its behaviour is the same as for destructors of static objects
147// (see ISO 14882:1998 "Programming languages -- C++" 3.6.3)
148//
149// The correct approach to deal with the problem would be to have memory manager
150// to properly control its memory allocation and caching free blocks so
151// as to release all memory as soon as it is returned to it, and probably
152// even delete itself if all memory it manages has been released and
153// last call to method Purge() was with True.
154//
155// Note that one possible method to control memory allocations could
156// be counting calls to Allocate() and Free()...
157//
158//=======================================================================
159
160static Standard_MMgrRoot* GetMMgr()
161{
162 static Standard_MMgrFactory aFactory;
163 return aFactory.myFMMgr;
164}
165
166//=======================================================================
167//function : Allocate
168//purpose :
169//=======================================================================
170
171Standard_Address Standard::Allocate(const Standard_Size size)
172{
173 return GetMMgr()->Allocate(size);
174}
175
176//=======================================================================
177//function : Free
178//purpose :
179//=======================================================================
180
181void Standard::Free(Standard_Address& aStorage)
182{
183 GetMMgr()->Free(aStorage);
184}
185
186//=======================================================================
187//function : Reallocate
188//purpose :
189//=======================================================================
190
191Standard_Address Standard::Reallocate(Standard_Address& aStorage,
192 const Standard_Size newSize)
193{
194 return GetMMgr()->Reallocate(aStorage, newSize);
195}
196
197//=======================================================================
198//function : Purge
199//purpose :
200//=======================================================================
201
202Standard_Integer Standard::Purge()
203{
204 return GetMMgr()->Purge();
205}
206
207//=======================================================================
208//function : IsReentrant
209//purpose :
210//=======================================================================
211
212Standard_Boolean Standard::IsReentrant()
213{
214 return Standard_IsReentrant;
215}
216
217//=======================================================================
218//function : SetReentrant
219//purpose :
220//=======================================================================
221
222void Standard::SetReentrant (const Standard_Boolean isReentrant)
223{
224 Standard_IsReentrant = isReentrant;
225 GetMMgr()->SetReentrant (isReentrant);
226}