1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/libraries/libmbutil/mynewmem.cc,v 1.28 2017/01/12 14:44:05 masarati Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati  <masarati@aero.polimi.it>
9  * Paolo Mantegazza     <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30  */
31 
32 /*****************************************************************************
33 
34 	Allocazione dinamica di memoria controllata con ASSERT e Memory Manager
35 
36 	Scritto da
37 	Pierangelo Masarati
38 	il 05/04/1997
39 
40  *****************************************************************************/
41 
42 #include "mbconfig.h"           /* This goes first in every *.c,*.cc file */
43 
44 #ifdef DEBUG
45 
46 #include <string.h>
47 #include <iostream>
48 #include <iomanip>
49 
50 #include "myassert.h"
51 #include "mynewmem.h"
52 
53 
54 /* Funzioni usate anche senza memory manager */
55 void
_Safenew(const char * file,int line,int flag)56 _Safenew(const char *file, int line, int flag)
57 {
58    	std::cout.flush();
59    	if (flag == 0) {
60       		std::cerr << std::endl
61 			<< "SAFENEW fault: NULL return pointer in file "
62 			<< file << " at line " << line << std::endl;
63    	} else if (flag == 1) {
64       		std::cerr << std::endl
65 			<< "SAFENEWARR fault: NULL return pointer in file "
66 			<< file << " at line " << line << std::endl;
67    	}
68 }
69 
70 
71 void
_Safenewfill(void * pv,size_t size,char fill)72 _Safenewfill(void *pv, size_t size, char fill)
73 {
74    	ASSERT(pv);
75    	ASSERT(size);
76 
77    	char* pb = (char*)pv;
78    	while (size--) {
79       		*pb++ = fill;
80    	}
81 }
82 
83 #ifdef DEBUG_MEMMANAGER
84 
85 clMemMan defaultMemoryManager("Default");
86 
87 /* Funzioni proprie private del memory manager */
88 clMemMan::stList *
pstFindElem(const void * pvToFind) const89 clMemMan::pstFindElem(const void* pvToFind) const
90 {
91    	ASSERT(pvToFind);
92 
93    	stList *pstL = pstRoot;
94    	ASSERT(pstL);
95 
96    	while (pstL->pstNext && (pstL->pstNext->stMB.pv <= pvToFind)) {
97       		pstL = pstL->pstNext;
98       		if (pstL->stMB.pv == pvToFind) {
99 	 		if (pstL->stMB.eSt == ALLOCATED) {
100 	    			return pstL;
101 	 		}
102       		}
103    	}
104    	CERR << std::endl << "clMemMan " << sName << " error: pointer "
105      		<< (void*)pvToFind << " not found in pstFindElem()" << std::endl;
106    	return NULL;
107 }
108 
109 clMemMan::stList *
pstFindPrev(const void * pvToFindPrev) const110 clMemMan::pstFindPrev(const void *pvToFindPrev) const
111 {
112    	ASSERT(pvToFindPrev);
113 
114    	stList *pstL = pstRoot;
115    	stList *pstN = NULL;
116    	ASSERT(pstL);
117 
118    	while (pstL->pstNext && (pstL->pstNext->stMB.pv <= pvToFindPrev)) {
119       		pstN = pstL->pstNext;
120       		if (pstN->stMB.pv == pvToFindPrev) {
121 	 		if (pstN->stMB.eSt == ALLOCATED) {
122 	    			return pstL;
123 	 		}
124       		}
125       		pstL = pstN;
126    	}
127 
128    	CERR << std::endl << "clMemMan " << sName << " error: pointer "
129      		<< (void*)pvToFindPrev << " not found in pstFindPrev()"
130 		<< std::endl;
131    	return NULL;
132 }
133 
134 /* enum eRemoveMode { RELEASE, DELBUTKEEPLOG, DELBUTNOTRELEASE }; */
135 void
_remove(const void * pvToRemove,clMemMan::eRemoveMode eMode,flag fArr,flag fFill)136 clMemMan::_remove(const void *pvToRemove, clMemMan::eRemoveMode eMode, flag fArr, flag fFill)
137 {
138    	ASSERT(pvToRemove);
139 
140    	stList *pstL = pstFindPrev(pvToRemove);
141    	ASSERT(pstL);
142 
143    	if (!pstL) {
144       		CERR << std::endl << "clMemMan " << sName << " warning: pointer "
145 			<< (void*)pvToRemove;
146       		if (fArr) {
147 	 		std::cerr << " to array";
148       		}
149       		std::cerr << " not found in _remove()" << std::endl;
150       		throw clMemMan::ErrNotFound();
151    	}
152 
153    	stList *pstN = pstL->pstNext;
154    	ASSERT(pstN);
155 
156    	if (fFill) {
157       		ASSERT(fArr && pstN->stMB.fArr);
158       		_Safenewfill(pstN->stMB.pv, pstN->stMB.size, cDebugFree);
159    	}
160 
161    	switch (eMode) {
162     	case RELEASE:
163 	   	/* caso di cancellazione totale */
164 	   	pstL->pstNext = pstN->pstNext;
165 	   	delete pstN;
166 	   	break;
167 
168     	case DELBUTKEEPLOG:
169 	   	/* Cancellazione della memoria mantenendo il registro */
170 	   	pstN->stMB.eSt = FREED;
171 	   	break;
172 
173     	case DELBUTNOTRELEASE:
174 	   	/* Eliminazione del riferimento senza cancellazione memoria */
175 	   	pstN->stMB.eSt = FREEDBUTNOTRELEASED;
176 	   	break;
177 	}
178 }
179 
180 /* Funzioni proprie pubbliche del memory manager */
clMemMan(char * sNameIn)181 clMemMan::clMemMan(char *sNameIn)
182 : pstRoot(NULL), sName(NULL)
183 {
184    	if (sNameIn) {
185       		sName = new char[strlen(sNameIn)+1];
186       		strcpy(sName, sNameIn);
187    	}
188 
189    	pstRoot = new stList(stMemBlock());
190 }
191 
~clMemMan(void)192 clMemMan::~clMemMan(void)
193 {
194    	stList* pstL = pstRoot;
195    	stList* pstP = NULL;
196    	ASSERT(pstL);
197 
198    	while (pstL) {
199       		pstP = pstL;
200       		pstL = pstL->pstNext;
201       		delete pstP;
202    	}
203 
204    	if (sName) {
205       		delete[] sName;
206    	}
207 }
208 
209 flag
fIsBlock(const void * pvBlock,size_t sizeBlock) const210 clMemMan::fIsBlock(const void *pvBlock, size_t sizeBlock) const
211 {
212    	ASSERT(pvBlock);
213    	ASSERT(sizeBlock);
214 
215    	stList *pstL = pstFindElem(pvBlock);
216    	ASSERT(pstL);
217 
218    	if (pstL && (pstL->stMB.size == sizeBlock)) {
219       		ASSERT(pstL->stMB.eSt != UNKNOWN);
220       		if (pstL->stMB.eSt == ALLOCATED) {
221 	 		return 1;
222       		}
223    	}
224 
225    	return 0;
226 }
227 
228 flag
fIsPointerToBlock(const void * pvBlock) const229 clMemMan::fIsPointerToBlock(const void *pvBlock) const
230 {
231    	ASSERT(pvBlock);
232 
233    	stList *pstL = pstFindElem(pvBlock);
234    	ASSERT(pstL);
235 
236    	if (pstL) {
237       		ASSERT(pstL->stMB.eSt != UNKNOWN);
238       		if (pstL->stMB.eSt == ALLOCATED) {
239 	 		return 1;
240       		}
241    	}
242 
243    	return 0;
244 }
245 
246 flag
fIsValid(const void * pvValid,size_t sizeValid) const247 clMemMan::fIsValid(const void *pvValid, size_t sizeValid) const
248 {
249    	ASSERT(pvValid);
250    	ASSERT(sizeValid);
251 
252    	stList *pstL = pstRoot;
253    	ASSERT(pstL);
254 
255    	while (pstL->pstNext) {
256       		pstL = pstL->pstNext;
257       		flag fCond1 = (pstL->stMB.pv <= pvValid);
258       		flag fCond2 = (((void*)pstL->stMB.pv+pstL->stMB.size)
259 			>= ((void*)pvValid+sizeValid));
260 
261       		if (fCond1 && fCond2) {
262 	 		ASSERT(pstL->stMB.eSt != UNKNOWN);
263 	 		if (pstL->stMB.eSt == ALLOCATED) {
264 	    			return 1;
265 	 		}
266       		}
267    	}
268 
269    	return 0;
270 }
271 
272 size_t
sizeOfBlock(const void * pvSizeOf) const273 clMemMan::sizeOfBlock(const void* pvSizeOf) const
274 {
275    	ASSERT(pvSizeOf);
276    	stList *pstL = pstFindElem(pvSizeOf);
277    	ASSERT(pstL);
278 
279    	if (pstL) {
280       		return pstL->stMB.size;
281    	}
282 
283    	return 0;
284 }
285 
286 
287 flag
fIsArray(const void * pvIsArray) const288 clMemMan::fIsArray(const void *pvIsArray) const
289 {
290    	ASSERT(pvIsArray);
291    	stList *pstL = pstFindElem(pvIsArray);
292    	ASSERT(pstL);
293 
294    	if (pstL) {
295       		return pstL->stMB.fArr;
296    	}
297    	return 0;
298 }
299 
300 eStatus
eBlockStatus(const void * pvBStatus) const301 clMemMan::eBlockStatus(const void *pvBStatus) const
302 {
303    	ASSERT(pvBStatus);
304    	stList *pstL = pstFindElem(pvBStatus);
305    	ASSERT(pstL);
306 
307    	if (pstL) {
308       		return pstL->stMB.eSt;
309    	}
310    	return UNKNOWN;
311 }
312 
313 void
ClearRefs(void)314 clMemMan::ClearRefs(void)
315 {
316    	stList *pstL = pstRoot;
317    	ASSERT(pstL);
318 
319    	while(pstL->pstNext) {
320       		pstL = pstL->pstNext;
321       		pstL->stMB.fRef = 0;
322    	}
323 }
324 
325 void
PutRef(const void * pvRef)326 clMemMan::PutRef(const void *pvRef)
327 {
328    	ASSERT(pvRef);
329 
330    	stList *pstL = pstFindElem(pvRef);
331    	ASSERT(pstL);
332 
333    	if (pstL) {
334       		pstL->stMB.fRef = 1;
335    	}
336 }
337 
338 flag
fIsRefd(const void * pvIsRefd) const339 clMemMan::fIsRefd(const void *pvIsRefd) const
340 {
341    	ASSERT(pvIsRefd);
342 
343    	stList *pstL = pstFindElem(pvIsRefd);
344    	ASSERT(pstL);
345 
346    	if (pstL && (pstL->stMB.eSt == ALLOCATED) && (pstL->stMB.fRef == 1)) {
347       		return 1;
348    	}
349 
350    	return 0;
351 }
352 
353 /* enum eStatus { UNKNOWN, ALLOCATED, FREED, FREEDBUTNOTRELEASED }; */
354 std::ostream&
DumpRef(std::ostream & rout) const355 clMemMan::DumpRef(std::ostream& rout) const
356 {
357    	rout << "Memory Manager 1.0";
358    	if (sName) {
359 		rout << ": " << sName;
360 	}
361    	rout << std::endl;
362 
363    	rout << "Ref'd blocks:" << std::endl;
364 
365    	stList *pstL = pstRoot;
366    	ASSERT(pstL);
367 
368    	int iCount = 0;
369    	while (pstL->pstNext) {
370       		pstL = pstL->pstNext;
371       		ASSERT(pstL->stMB.eSt != UNKNOWN);
372 
373       		iCount++;
374       		if (pstL->stMB.fRef) {
375 	 		rout << "Block " << setw(4) << iCount << ':' << std::endl
376 	   			<< "pointer " << pstL->stMB.pv
377 	   			<< ", size " << pstL->stMB.size
378 	   			<< ", status: ";
379 
380 	 		if (pstL->stMB.eSt == ALLOCATED) {
381 	    			rout << "ALLOCATED" << std::endl;
382 	 		} else if (pstL->stMB.eSt == FREED) {
383 	    			rout << "FREED" << std::endl;
384 	 		} else if (pstL->stMB.eSt == FREEDBUTNOTRELEASED) {
385 	    			rout << "FREEDBUTNOTRELEASED" << std::endl;
386 	 		}
387       		}
388    	}
389 
390    	rout << "Unref'd blocks:" << std::endl;
391 
392    	pstL = pstRoot;
393    	iCount = 0;
394    	while (pstL->pstNext) {
395       		pstL = pstL->pstNext;
396       		ASSERT(pstL->stMB.eSt != UNKNOWN);
397 
398       		iCount++;
399       		if (!pstL->stMB.fRef) {
400 	 		rout << "Block " << setw(4) << iCount << ':' << std::endl
401 	   			<< "pointer " << pstL->stMB.pv
402 	   			<< ", size " << pstL->stMB.size
403 	   			<< ", status: ";
404 
405 	 		if (pstL->stMB.eSt == ALLOCATED) {
406 	    			rout << "ALLOCATED" << std::endl;
407 	 		} else if (pstL->stMB.eSt == FREED) {
408 	    			rout << "FREED" << std::endl;
409 	 		} else if (pstL->stMB.eSt == FREEDBUTNOTRELEASED) {
410 	    			rout << "FREEDBUTNOTRELEASED" << std::endl;
411 	 		}
412       		}
413    	}
414 
415    	return rout;
416 }
417 
418 void
add(const void * pvIn,size_t sizeIn,flag fArr)419 clMemMan::add(const void *pvIn, size_t sizeIn, flag fArr)
420 {
421    	ASSERT(pvIn);
422    	ASSERT(sizeIn);
423    	ASSERT(fArr == 0 || fArr == 1);
424 
425    	stList *pstL = pstRoot;
426    	stList *pstN = NULL;
427    	ASSERT(pstL);
428 
429    	while (pstL->pstNext) {
430       		pstN = pstL->pstNext;
431       		if ((pstN->stMB.pv == pvIn) && (pstN->stMB.eSt == ALLOCATED)) {
432 	 		CERR << std::endl << "clMemMan" << sName
433 	   			<< " error: block pointed by "
434 	   			<< (void*)pvIn << ", size " << sizeIn << std::endl
435 	   			<< "is already defined. Previous size is "
436 	   			<< pstN->stMB.size << std::endl;
437 	 		return;
438       		}
439 
440       		if (pstN->stMB.pv >= pvIn) {
441 	 		break;
442       		}
443       		pstL = pstN;
444    	}
445 
446    	pstN = new stList(stMemBlock((void*)pvIn, sizeIn, ALLOCATED, fArr));
447    	ASSERT(pstN);
448 
449    	if (pstN == NULL) {
450       		CERR << std::endl << "clMemMan " << sName
451 			<< ": error in allocation in add()" << std::endl;
452       		throw ErrMemory(MBDYN_EXCEPT_ARGS);
453    	}
454 
455    	pstN->pstNext = pstL->pstNext;
456    	pstL->pstNext = pstN;
457 }
458 
459 /* Operatore friend del memory manager */
460 std::ostream&
operator <<(std::ostream & rout,const clMemMan & rm)461 operator << (std::ostream& rout, const clMemMan& rm)
462 {
463    	rout << "Memory Manager 1.0";
464    	if (rm.sName) {
465       		rout << ": " << rm.sName;
466    	}
467    	rout << std::endl;
468 
469    	clMemMan::stList *pstL = rm.pstRoot;
470 
471    	int iCount = 0;
472    	while (pstL->pstNext) {
473       		pstL = pstL->pstNext;
474       		ASSERT(pstL->stMB.eSt != UNKNOWN);
475 
476       		rout << "Block " << setw(4) << (++iCount) << ':' << std::endl
477 			<< "pointer " << pstL->stMB.pv
478 			<< ", size " << pstL->stMB.size
479 			<< ", status: ";
480 
481       		if (pstL->stMB.eSt == ALLOCATED) {
482 	 		rout << "ALLOCATED" << std::endl;
483       		} else if (pstL->stMB.eSt == FREED) {
484 	 		rout << "FREED" << std::endl;
485       		} else if (pstL->stMB.eSt == FREEDBUTNOTRELEASED) {
486 	 		rout << "FREEDBUTNOTRELEASED" << std::endl;
487       		}
488    	}
489 
490    	return rout;
491 }
492 
493 #endif /* DEBUG_MEMMANAGER */
494 
495 #endif /* DEBUG */
496 
497