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