1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/libraries/libmbutil/mynewmem.h,v 1.24 2017/01/12 14:44:05 masarati Exp $ */ 2 /* 3 * This library comes with MBDyn (C), a multibody analysis code. 4 * http://www.mbdyn.org 5 * 6 * Copyright (C) 1996-2017 7 * 8 * Pierangelo Masarati <masarati@aero.polimi.it> 9 * 10 * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano 11 * via La Masa, 34 - 20156 Milano, Italy 12 * http://www.aero.polimi.it 13 * 14 * Changing this copyright notice is forbidden. 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License as published by 18 * the Free Software Foundation (version 2 of the License). 19 * 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 29 */ 30 31 /****************************************************************************** 32 33 Allocazione dinamica di memoria controllata con ASSERT e Memory Manager 34 35 36 Scritto da 37 Pierangelo Masarati 38 il 05/04/1997 39 40 41 Se si usa #define DEBUG sono attivate solo le routines di ASSERT; 42 43 Se si usa anche #define DEBUG_MEMMANAGER, viene attivato il memory manager. 44 45 Se si aggiunge #define DEBUG_MEMMANAGER_DELETEBUTKEEPLOG, quando un blocco 46 viene cancellato, ne rimane traccia nel log. 47 48 Se si aggiunge #define DEBUG_MEMMANAGER_DELETEBUTNOTRELEASE, quando un blocco 49 viene cancellato in realta' la memoria non viene mai rilasciata, solo se ne 50 perde il riferimento 51 52 53 E' necessario aggiungere al makefile i seguenti files: 54 55 <myassert.cc> 56 <mynewmem.cc> 57 58 Inoltre e' necessario mettere questa intestazione in tutti i files che 59 usano la gestione sicura della memoria: 60 61 #define DEBUG 62 #define DEBUG_MEMMANAGER 63 [ #define DEBUG_MEMMANAGER_DELETEBUTKEEPLOG || 64 #define DEBUG_MEMMANAGER_DELETEBUTNOTRELEASE ] 65 #include "mynewmem.h" 66 67 68 69 Le macro di gestione dinamica della memoria sono: 70 71 SAFENEW(item* pit, item); 72 SAFENEW_(item* pit, item, clMemMan mm); 73 <pit> e' un puntatore al tipo <item> e deve essere <pit> = NULL 74 <item> e' un tipo valido 75 <mm> e' un oggetto della classe clMemMan 76 se #ifdef DEBUG_MEMMANAGER = TRUE, 77 altrimenti non viene usato 78 ### 79 ### ATTENZIONE: QUANDO SI USA LA MACRO "SAFENEW", O <item> E' UN TIPO 80 ### SEMPLICE, IL CUI COSTRUTTORE NON CREA EFFETTI COLLATERALI 81 ### (ALLORA SI PUO' USARE IL COSTRUTTORE AL POSTO DI <item>), 82 ### OPPURE SI DESIDERA UTILIZZARE IL COSTRUTTORE DI DEFAULT. 83 ### SE SI DEVE UTILIZZARE UN COSTRUTTORE COMPLESSO, E' NECESSARIO 84 ### USARE LA MACRO "SAFENEWWITHCONSTRUCTOR" 85 ### (ED E' CONSIGLIABILE USARLA SEMPRE PER TIPI COMPLESSI, ALTRIMENTI 86 ### PUO' ESSERE ESEGUITO PIU' VOLTE IL COSTRUTTORE 87 ### 88 89 SAFENEWWCONS(item* pit, item, constructor); 90 SAFENEWWITHCONSTRUCTOR_(item* pit, item, constructor, clMemMan mm); 91 <pit> e' un puntatore al tipo <item> e deve essere <pit> = NULL 92 <item> e' un tipo valido 93 <constructor> ' il costruttore di <item> 94 <mm> e' un oggetto della classe clMemMan 95 se #ifdef DEBUG_MEMMANAGER = TRUE, 96 altrimenti non viene usato 97 98 SAFENEWARR(item* pit, item, type size); 99 SAFENEWARR_(item* pit, item, type size, clMemMan mm); 100 come SAFENEW, solo che viene allocato un array di oggetti 101 di tipo <item> dalle dimensioni determinate da <size>, 102 di tipo indefinito. 103 104 105 106 SAFEDELETE(item* pit); 107 SAFEDELETE_(item* pit, clMemMan mm); 108 come sopra; <pit> deve essere definito e deve essere 109 contenuto in <mm> in qualita' di puntatore all'inizio 110 di un blocco se #ifdef DEBUG_MEMMANAGER = TRUE 111 112 SAFEDELETEARR(item* pit); 113 SAFEDELETEARR_(item* pit, clMemMan mm); 114 come SAFEDELETE, solo che viene cancellata un'array di oggetti. 115 116 SAFEDELETEANDFILLARR(item* pit); 117 SAFEDELETEANDFILLARR_(item* pit, clMemMan mm); 118 come SAFEDELETEARR, ma se #ifdef DEBUG_MEMMANAGER = TRUE, 119 prima di deallocare riempe la memoria con il carattere di free; 120 deve essere usato solo quando ogni oggetto dell'array e' stato 121 distrutto con l'apposito distruttore, oppure se gli oggetti 122 non hanno distruttore (verificare come viene distrutto un 123 array di oggetti con distruttore) 124 125 126 Uso: 127 128 item* pit = NULL; 129 clMemMan m; 130 131 // per allocare: 132 SAFENEW(pit, item, m); 133 134 if( pit == NULL) // Handle error 135 // L'errore puo' essere gestito in modo migliore attraverso 136 // il casting dell'operatore <new> in modo che non sia 137 // possibile mancare l'allocazione. 138 // In ogni caso la mancata allocazione viene segnalata 139 // su <cerr>. 140 141 // per deallocare: 142 SAFEDELETE(pit, m); 143 144 // In modo analogo si usano 145 SAFENEWARR(pit, item, size, m); 146 SAFEDELETEARR(pit, m); 147 SAFEDELETEANDFILLARR(pit, m); 148 149 150 Nota: per comportamenti particolari, agire sul codice 151 delle funzioni clMemMan::remove, clMemMan::removeAndFill 152 e delle macro SAFEDELETE(), SAFEDELETEARR() 153 per evitare il delete fisico della memoria o per mantenere un log 154 delle allocazioni avvenute. 155 156 157 158 class clMemMan : 159 160 La classe clMemMan e' un importante strumento di debugging. 161 Consente di mantenere informazioni relative alla memoria allocata 162 attraverso le macro e quindi di verificare in qualsiasi momento 163 se la memoria utilizzata e' effettivamente disponibile. 164 165 L'inserimento e la cancellazione dei record avviene automaticamente 166 tramite le macro. L'utente dispone di due strumenti di verifica. 167 Il primo consiste nel dump della struttura della memoria. In esso 168 i records sono ordinati in base al valore del puntatore a cui fanno 169 riferimento. Questo rende possibile una verifica manuale. 170 Il secondo strumento consiste nella possibilita' di marcare 171 i puntatori desiderati con un riferimento qualora siano effettiva- 172 mente disponibili. Quindi un dump dei riferimenti marcati consente 173 di verificare sia la presenza di garbage (memoria non piu' puntata 174 e quindi non referenziabile) che di dangling referencies (puntatori 175 a memoria non piu' disponibile). 176 177 178 179 Le funzioni pubbliche della classe sono: 180 181 flag clMemMan::fIsBlock(const void* pvBlock, size_t sizeBlock = 1) const; 182 se <pvBlock> e' un puntatore all'inizio di un blocco 183 e <sizeBlock> e' la corretta dimensione del blocco ritorna TRUE, 184 altrimenti FALSE 185 186 flag clMemMan::fIsPointerToBlock(const void* pvBlock) const; 187 se <pvBlock> e' un puntatore all'inizio di un blocco 188 ritorna TRUE, altrimenti FALSE 189 190 flag clMemMan::fIsValid(const void* pvValid, size_t sizeValid = 1) const; 191 se <pvValid> e' una valida locazione all'interno di un blocco e 192 <(void*)pvalid+sizeValid-1> non eccede il blocco ritorna TRUE, 193 altrimenti FALSE 194 195 size_t clMemMan::sizeOfBlock(const void* pvSizeOf) const; 196 se <pvSizeOf> e' un puntatore all'inizio di un blocco, 197 ne ritorna la dimensione 198 199 flag clMemMan::fIsArray(const void* pvIsArray) const; 200 se <pvIsArray> e' un puntatore all'inizio di un blocco, 201 ritorna TRUE se e' un'array, altrimenti FALSE 202 203 eStatus clMemMan::eBlockStatus(const void* pvBStatus) const; 204 se <pvIsArray> e' un puntatore all'inizio di un blocco, 205 ne ritorna lo stato con un valore appartenente all'enum <eStatus> 206 207 void clMemMan::ClearRefs(void); 208 azzera i flag di riferimento a tutti i puntatori 209 210 void clMemMan::PutRef(const void* pvRef); 211 se <pvRef> e' un puntatore all'inizio di un blocco, 212 ne setta il riferimento 213 214 flag clMemMan::fIsRefd(const void* pvIsRefd) const; 215 se <pvRef> e' un puntatore all'inizio di un blocco, 216 ritorna TRUE se il riferimento e' settato 217 218 void clMemMan::DumpRef(ostream& rout) const; 219 invia la stampa dei blocchi suddivisi in base ai riferimenti 220 ad un ostream 221 222 ostream& operator << (ostream& rout, const clMemMan& rm); 223 invia la stampa dei blocchi con le relative proprieta' ad un ostream 224 225 226 Esempio completo: 227 228 // ... 229 230 #define DEBUG 231 #define DEBUG_MEMMANAGER 232 #include "mynewmem.h" 233 234 // ... 235 236 // Uso dei riferimenti: 237 238 #ifdef DEBUG_MEMMANAGER 239 clMemMan m("Test"); // Memory Manager 240 #endif 241 242 void* pb = NULL; 243 SAFENEW(pb, char, m); // Allocazione di un byte 244 245 #ifdef DEBUG_MEMMANAGER 246 m.ClearRefs(); // Pulisce i Ref 247 m.PutRef(pb); // Setta il Ref di pb 248 if (m.fIsRefd(pb)) { // Ritorna TRUE 249 m.DumpRef(cout); // scrive i dati 250 } 251 #endif 252 253 SAFEDELETE(pb, m); // Deallocazione 254 if (pb) { // Ritorna FALSE, perche' SAFEDELETE 255 NULL; // pone comunque pb = NULL 256 } 257 258 // Uso delle utilities: 259 260 SAFENEWARR(pb, char, 10, m); // Allocazione di 10 bytes 261 262 #ifdef DEBUG_MEMMANAGER 263 if (m.fIsPointerToBlock(pb), 10) { // Ritorna TRUE 264 size_t size = m.sizeOfBlock(pb);// Dim. del blocco 265 int iItems = 1; 266 if (m.fIsArray(pb)) { // Se array calcola le dim. 267 iItems = size/sizeof(*pb); 268 cout << "\nNumero di elementi: " 269 << iItems << endl; 270 } 271 void* pbTmp = pb; 272 while (size--) { // Azzera la memoria 273 // (operazione da non fare 274 *pbTmp++ = '\0';// se devono essere eseguiti 275 // i distruttori 276 } 277 } 278 #endif 279 SAFEDELETEARR(pb, m); // Libera la memoria 280 281 282 Si noti come, togliendo #define DEBUG_MEMMANAGER, si abbia il codice 283 di debug semplificato, con gli ASSERT ed altri controlli, mentre, 284 togliendo anche #define DEBUG, si abbia in modo autometico il codice 285 in versione release, senza alcun overhead 286 287 ******************************************************************************/ 288 289 #ifndef MYNEWMEM_H 290 #define MYNEWMEM_H 291 292 293 #include <myassert.h> 294 #include <except.h> 295 296 #ifdef DEBUG 297 298 /* Dichiarazione di funzioni usate nella versione debug */ 299 extern void _Safenew(const char* file, int line, int flag = 0); 300 extern void _Safenewfill(void* pv, size_t size, char fill); 301 302 const char cDebugAlloc = 'A'; 303 const char cDebugFree = 'F'; 304 305 #ifdef DEBUG_MEMMANAGER 306 307 /* Dichiarazione delle macro di debug con memory manager */ 308 #define SAFENEW_(pnt, item, memman) \ 309 do { \ 310 ASSERT(!(pnt)); \ 311 ASSERT(sizeof(item)); \ 312 (pnt) = new item; \ 313 if (!(pnt)) { \ 314 _Safenew(__FILE__, __LINE__); \ 315 } \ 316 (memman).add((void*)(pnt), sizeof(item)); \ 317 } while(0) 318 319 /* Dichiarazione delle macro di debug con memory manager */ 320 #define SAFENEWWITHCONSTRUCTOR_(pnt, item, constructor, memman) \ 321 do { \ 322 ASSERT(!(pnt)); \ 323 ASSERT(sizeof(item)); \ 324 (pnt) = new constructor; \ 325 if (!(pnt)) { \ 326 _Safenew(__FILE__, __LINE__); \ 327 } \ 328 (memman).add((void*)(pnt), sizeof(item)); \ 329 } while (0) 330 331 /* Attenzione: questa operazione e' lecita solo se 332 * non e' stato eseguito un costruttore 333 * _Safenewfill(pnt, sizeof(item), cDebugAlloc); */ 334 #define SAFENEWARR_(pnt, item, sz, memman) \ 335 do { \ 336 ASSERT(!(pnt)); \ 337 ASSERT(sizeof(item)); \ 338 ASSERT(sz); \ 339 (pnt) = new item[sz]; \ 340 if (!(pnt)) { \ 341 _Safenew(__FILE__, __LINE__, 1); \ 342 } \ 343 (memman).add((void*)(pnt), sizeof(item)*(sz), 1); \ 344 _Safenewfill((void*)pnt, sizeof(item)*(sz), cDebugAlloc); \ 345 } while (0) 346 347 /* questa e' sicura anche se e' stato eseguito un costruttore */ 348 #define SAFENEWARRNOFILL_(pnt, item, sz, memman) \ 349 do { \ 350 ASSERT(!(pnt)); \ 351 ASSERT(sizeof(item)); \ 352 ASSERT(sz); \ 353 (pnt) = new item[sz]; \ 354 if (!(pnt)) { \ 355 _Safenew(__FILE__, __LINE__, 1); \ 356 } \ 357 (memman).add((void*)(pnt), sizeof(item)*(sz), 1); \ 358 } while (0) 359 360 #define SAFESTRDUP_(pnt, src, memman) \ 361 do { \ 362 ASSERT(!(pnt)); \ 363 ASSERT((src)); \ 364 unsigned int l = strlen((src))+1; \ 365 (pnt) = new char[l]; \ 366 if ( !(pnt) ) { \ 367 _Safenew(__FILE__, __LINE__, 1); \ 368 } \ 369 strcpy((char *)(pnt), (src)); \ 370 (memman).add((void*)(pnt), l, 1); \ 371 } while (0) 372 373 /* Qui il fill e' lecito perche' per le arrays 374 * non sono eseguiti i costruttori */ 375 376 #ifndef DEBUG_MEMMANAGER_DELETEBUTKEEPLOG 377 378 #ifndef DEBUG_MEMMANAGER_DELETEBUTNOTRELEASE 379 380 #define SAFEDELETE_(pnt, memman) \ 381 do { \ 382 ASSERT(pnt); \ 383 (memman).remove((void*)(pnt)); \ 384 delete (pnt); \ 385 (pnt) = NULL; \ 386 } while (0) 387 388 #define SAFEDELETEARR_(pnt, memman) \ 389 do { \ 390 ASSERT(pnt); \ 391 (memman).remove((void*)(pnt), 1); \ 392 delete[] (pnt); \ 393 (pnt) = NULL; \ 394 } while (0) 395 396 #define SAFEDELETEANDFILLARR_(pnt, memman) \ 397 do { \ 398 ASSERT(pnt); \ 399 (memman).remove((void*)(pnt), 1, 1); \ 400 delete[] (pnt); \ 401 (pnt) = NULL; \ 402 } while (0) 403 404 #endif /* !DEBUG_MEMMANAGER_DELETEBUTNOTRELEASE */ 405 406 #endif /* !DEBUG_MEMMANAGER_DELETEBUTKEEPLOG */ 407 408 #ifdef DEBUG_MEMMANAGER_DELETEBUTKEEPLOG 409 410 #define SAFEDELETE_(pnt, memman) \ 411 do { \ 412 ASSERT(pnt); \ 413 (memman).removeButKeepLog((void*)(pnt)); \ 414 delete (pnt); \ 415 (pnt) = NULL; \ 416 } while (0) 417 418 #define SAFEDELETEARR_(pnt, memman) \ 419 do { \ 420 ASSERT(pnt); \ 421 (memman).removeButKeepLog((void*)(pnt), 1); \ 422 delete[] (pnt); \ 423 (pnt) = NULL; \ 424 } while (0) 425 426 #define SAFEDELETEANDFILLARR_(pnt, memman) \ 427 do { \ 428 ASSERT(pnt); \ 429 (memman).removeButKeepLog((void*)(pnt), 1); \ 430 delete[] (pnt); \ 431 (pnt) = NULL; \ 432 } while (0) 433 434 #endif /* DEBUG_MEMMANAGER_DELETEBUTKEEPLOG */ 435 436 #ifdef DEBUG_MEMMANAGER_DELETEBUTNOTRELEASE 437 438 #define SAFEDELETE_(pnt, memman) \ 439 do { \ 440 ASSERT(pnt); \ 441 (memman).removeButNotRelease((void*)(pnt)); \ 442 delete (pnt); \ 443 (pnt) = NULL; \ 444 } while (0) 445 446 #define SAFEDELETEARR_(pnt, memman) \ 447 do { \ 448 ASSERT(pnt); \ 449 (memman).removeButNotRelease((void*)(pnt), 1); \ 450 delete[] (pnt); \ 451 (pnt) = NULL; \ 452 } while (0) 453 454 #define SAFEDELETEANDFILLARR_(pnt, memman) \ 455 do { \ 456 ASSERT(pnt); \ 457 (memman).removeButNotRelease((void*)(pnt), 1); \ 458 delete[] (pnt); \ 459 (pnt) = NULL; \ 460 } while (0) 461 462 #endif /* DEBUG_MEMMANAGER_DELETEBUTNOTRELEASE */ 463 464 /* enum degli stati della memoria */ 465 enum eStatus { 466 UNKNOWN, 467 ALLOCATED, 468 FREED, 469 FREEDBUTNOTRELEASED 470 }; 471 472 /* struttura dei dati di un blocco di memoria */ 473 struct stMemBlock { 474 void* pv; 475 size_t size; 476 eStatus eSt; 477 flag fArr; 478 flag fRef; 479 480 stMemBlock(void* _pv = NULL, size_t _size = 0, eStatus _eSt = UNKNOWN, 481 flag _fArr = 0, flag _fRef = 0) pvstMemBlock482 : pv(_pv), size(_size), eSt(_eSt), fArr(_fArr), fRef(_fRef) { 483 NO_OP; 484 }; 485 }; 486 487 /* classe del memory manager */ 488 class clMemMan { 489 friend ostream& operator << (ostream& rout, const clMemMan& rm); 490 491 public: 492 class ErrGeneric : public MBDynErrBase { 493 public: ErrGeneric(MBDYN_EXCEPT_ARGS_DECL)494 ErrGeneric(MBDYN_EXCEPT_ARGS_DECL) : MBDynErrBase(MBDYN_EXCEPT_ARGS_PASSTHRU) {}; 495 }; 496 class ErrNotFound : public MBDynErrBase { 497 public: ErrNotFound(MBDYN_EXCEPT_ARGS_DECL)498 ErrNotFound(MBDYN_EXCEPT_ARGS_DECL) : MBDynErrBase(MBDYN_EXCEPT_ARGS_PASSTHRU) {}; 499 }; 500 501 private: 502 struct stList { 503 stMemBlock stMB; 504 stList* pstNext; stListstList505 stList(stMemBlock stIn) : stMB(stIn), pstNext(NULL) { 506 NO_OP; 507 }; 508 }; 509 510 stList* pstRoot; 511 char* sName; 512 513 stList* pstFindElem(const void* pvToFind) const; 514 stList* pstFindPrev(const void* pvToFindPrev) const; 515 516 enum eRemoveMode { 517 RELEASE, 518 DELBUTKEEPLOG, 519 DELBUTNOTRELEASE 520 }; 521 522 void _remove(const void* pvToRemove, eRemoveMode eMode, flag fArr, 523 flag fFill); 524 525 public: 526 clMemMan(char* sName = NULL); 527 ~clMemMan(void); 528 529 flag fIsBlock(const void* pvBlock, size_t sizeBlock = 1) const; 530 flag fIsPointerToBlock(const void* pvBlock) const; 531 flag fIsValid(const void* pvValid, size_t sizeValid = 1) const; 532 size_t sizeOfBlock(const void* pvSizeOf) const; 533 flag fIsArray(const void* pvIsArray) const; 534 eStatus eBlockStatus(const void* pvBStatus) const; 535 536 void ClearRefs(void); 537 void PutRef(const void* pvRef); 538 flag fIsRefd(const void* pvIsRefd) const; 539 ostream& DumpRef(ostream& rout) const; 540 541 void add(const void* pvIn, size_t sizeIn, flag fArr = 0); 542 inline void remove(const void* pvToRemove, flag fArr = 0, flag fFill = 0) { 543 _remove(pvToRemove, RELEASE, fArr, fFill); 544 }; 545 546 inline void removeButNotRelease(const void* pvToRemove, flag fArr = 0, flag fFill = 0) { 547 _remove(pvToRemove, DELBUTNOTRELEASE, fArr, fFill); 548 }; 549 550 inline void removeButKeepLog(const void* pvToRemove, flag fArr = 0, flag fFill = 0) { 551 _remove(pvToRemove, DELBUTKEEPLOG, fArr, fFill); 552 }; 553 }; 554 555 extern clMemMan defaultMemoryManager; 556 557 /* funzione di stream del memory manager */ 558 extern ostream& operator << (ostream& rout, const clMemMan& rm); 559 560 #else /* !DEBUG_MEMMANAGER */ 561 562 /* dichiarazione delle macro di debug senza memory manager */ 563 #define SAFENEW_(pnt, item, memman) \ 564 do { \ 565 ASSERT(!(pnt)); \ 566 ASSERT(sizeof(item)); \ 567 (pnt) = new item; \ 568 if (!(pnt)) { \ 569 _Safenew(__FILE__, __LINE__); \ 570 } \ 571 } while (0) 572 573 /* Dichiarazione delle macro di debug senza memory manager */ 574 #define SAFENEWWITHCONSTRUCTOR_(pnt, item, constructor, memman) \ 575 do { \ 576 ASSERT(!(pnt)); \ 577 ASSERT(sizeof(item)); \ 578 (pnt) = new constructor; \ 579 if (!(pnt)) { \ 580 _Safenew(__FILE__, __LINE__); \ 581 } \ 582 } while (0) 583 584 /* Attenzione: questa operazione e' lecita solo se 585 * non e' stato eseguito un costruttore 586 * _Safenewfill(pnt, sizeof(item), cDebugAlloc) */ 587 588 #define SAFENEWARR_(pnt, item, sz, memman) \ 589 do { \ 590 ASSERT(!(pnt)); \ 591 ASSERT(sizeof(item)); \ 592 ASSERT(sz); \ 593 (pnt) = new item[sz]; \ 594 if (!(pnt)) { \ 595 _Safenew(__FILE__, __LINE__, 1); \ 596 } \ 597 _Safenewfill(pnt, sizeof(item)*(sz), cDebugAlloc); \ 598 } while (0) 599 600 /* questa e' sicura anche se e' stato eseguito un costruttore */ 601 #define SAFENEWARRNOFILL_(pnt, item, sz, memman) \ 602 do { \ 603 ASSERT(!(pnt)); \ 604 ASSERT(sizeof(item)); \ 605 ASSERT(sz); \ 606 (pnt) = new item[sz]; \ 607 if (!(pnt)) { \ 608 _Safenew(__FILE__, __LINE__, 1); \ 609 } \ 610 } while (0) 611 612 #define SAFESTRDUP_(pnt, src, memman) \ 613 do { \ 614 ASSERT(!(pnt)); \ 615 ASSERT((src)); \ 616 unsigned int l = strlen((src))+1; \ 617 (pnt) = new char[l]; \ 618 if (!(pnt)) { \ 619 _Safenew(__FILE__, __LINE__, 1); \ 620 } \ 621 strcpy((char *)(pnt), (src)); \ 622 } while (0) 623 624 /* Qui il fill e' lecito perche' per le arrays 625 * non sono eseguiti i costruttori */ 626 627 #define SAFEDELETE_(pnt, memman) \ 628 do { \ 629 ASSERT((pnt) != 0); \ 630 delete (pnt); \ 631 (pnt) = NULL; \ 632 } while (0) 633 634 #define SAFEDELETEARR_(pnt, memman) \ 635 do { \ 636 ASSERT((pnt) != 0); \ 637 delete[] (pnt); \ 638 (pnt) = NULL; \ 639 } while (0) 640 641 #define SAFEDELETEANDFILLARR_(pnt, memman) \ 642 do { \ 643 ASSERT((pnt) != 0); \ 644 delete[] (pnt); \ 645 (pnt) = NULL; \ 646 } while (0) 647 648 #endif /* !DEBUG_MEMMANAGER */ 649 650 #else /* !DEBUG */ 651 652 /* dichiarazione delle macro nella versione da release */ 653 #define SAFENEW_(pnt, item, memman) \ 654 (pnt) = new item 655 656 /* dichiarazione delle macro nella versione da release */ 657 #define SAFENEWWITHCONSTRUCTOR_(pnt, item, constructor, memman) \ 658 (pnt) = new constructor 659 660 #define SAFENEWARR_(pnt, item, sz, memman) \ 661 (pnt) = new item[sz] 662 663 #define SAFENEWARRNOFILL_(pnt, item, sz, memman) \ 664 (pnt) = new item[sz] 665 666 #define SAFESTRDUP_(pnt, src, memman) \ 667 do { \ 668 unsigned int l = strlen((src))+1; \ 669 (pnt) = new char[l]; \ 670 strcpy((char *)(pnt), (src)); \ 671 } while (0) 672 673 #define SAFEDELETE_(pnt, memman) \ 674 do { \ 675 delete (pnt); \ 676 (pnt) = NULL; \ 677 } while (0) 678 679 #define SAFEDELETEARR_(pnt, memman) \ 680 do { \ 681 delete[] (pnt); \ 682 (pnt) = NULL; \ 683 } while (0) 684 685 #define SAFEDELETEANDFILLARR_(pnt, memman) \ 686 do { \ 687 delete[] (pnt); \ 688 (pnt) = NULL; \ 689 } while (0) 690 691 #define defaultMemoryManager 0 692 693 #endif /* !DEBUG */ 694 695 #define SAFENEW(pnt, item) \ 696 SAFENEW_(pnt, item, defaultMemoryManager) 697 698 #define SAFENEWWITHCONSTRUCTOR(pnt, item, constructor) \ 699 SAFENEWWITHCONSTRUCTOR_(pnt, item, constructor, defaultMemoryManager) 700 701 #define SAFENEWARR(pnt, item, sz) \ 702 SAFENEWARR_(pnt, item, sz, defaultMemoryManager) 703 704 #define SAFENEWARRNOFILL(pnt, item, sz) \ 705 SAFENEWARRNOFILL_(pnt, item, sz, defaultMemoryManager) 706 707 #define SAFESTRDUP(pnt, src) \ 708 SAFESTRDUP_(pnt, src, defaultMemoryManager) 709 710 #define SAFEDELETE(pnt) \ 711 SAFEDELETE_(pnt, defaultMemoryManager) 712 713 #define SAFEDELETEARR(pnt) \ 714 SAFEDELETEARR_(pnt, defaultMemoryManager) 715 716 #define SAFEDELETEANDFILLARR(pnt) \ 717 SAFEDELETEANDFILLARR_(pnt, defaultMemoryManager) 718 719 #endif /* MYNEWMEM_H */ 720 721