1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6
7 #ifdef USE_OMP
8 #include <omp.h>
9 #endif
10
11 #include "replaceXt.h" /* 09 Nov 2018 */
12
13 #include "mcw_malloc.h"
14 #include "Amalloc.h"
15
16 #ifdef ALLOW_MCW_MALLOC
17 /*--------------------------------------------------------------------------
18 24 Jan 2001: Modified heavily to use a hash table instead of a linear
19 array to store the data about each allocated block.
20 16 Feb 2001: Modified to include some debug traceback info (if
21 USE_TRACING is defined - searce for TRAC to see code).
22 -- RWCox
23 ----------------------------------------------------------------------------*/
24
25 #define MAGIC ((char) 0xd7)
26 #define NEXTRA (2*sizeof(int))
27
28 #undef malloc
29 #undef realloc
30 #undef calloc
31 #undef free
32 #undef strdup
33 #undef XtMalloc
34 #undef XtRealloc
35 #undef XtFree
36 #undef XtCalloc
37 #undef mcw_malloc
38 #undef mcw_realloc
39 #undef mcw_calloc
40 #undef mcw_free
41 #undef mcw_strdup
42
43 #undef UINT
44 #define UINT unsigned int
45
46 #ifdef USE_TRACING /* 16 Feb 2001 */
47 # include "debugtrace.h"
48 # undef NTB /* number of traceback levels to keep for each malloc() */
49 # define NTB 5 /* (chosen to make sizeof(mallitem) a multiple of 8) */
50 #endif
51
52 /*-- struct to hold info about each malloc()-ed block --*/
53
54 typedef struct {
55 void * pmt ; /* pointer to actually malloc-ed block */
56 size_t psz ; /* size of allocated block */
57 char * pfn ; /* function name that called */
58 int pln ; /* function line number */
59 UINT pss ; /* serial number of this malloc */
60 #ifdef USE_TRACING
61 char * ptb[NTB] ; /* traceback from debugtrace.h */
62 #endif
63 } mallitem ;
64
65 /** set hash table size (to a prime number, please) **/
66
67 /** #define SLOTS 503 **/ /* a little small */
68
69 #define SLOTS 8191
70
71 /** #define SLOTS 16381 **/
72 /** #define SLOTS 32003 **/
73
74 static mallitem ** htab = NULL ; /* table of lists */
75 static int * nhtab = NULL ; /* size of each list */
76 static UINT serial = 0 ; /* serial number of allocation */
77
78 #undef INLINE
79 #ifdef __GNUC__
80 # define INLINE inline
81 #else
82 # define INLINE /*nada*/
83 #endif
84
85 #ifdef USE_TRACING
86 # define ADD_TRACEBACK(ip) \
87 do{ int tt ; \
88 for( tt=1 ; tt <= NTB ; tt++ ) \
89 ip->ptb[tt-1] = (tt < DBG_num) ? DBG_rout[DBG_num-tt] : NULL; } while(0)
90 #else
91 # define ADD_TRACEBACK(ip) /* nada */
92 #endif
93
94 /*---------------------------------------------------------------
95 Compute a unique non-negative integer key from an address
96 -----------------------------------------------------------------*/
97
mallkey(char * fred)98 static INLINE UINT mallkey( char * fred )
99 {
100 UINT q = (UINT)(intptr_t)fred ;
101
102 q = ((q & 0xf0f0f0f0) >> 4) /* swap nibbles */
103 | ((q & 0x0f0f0f0f) << 4) ;
104
105 return q ;
106 }
107
108 /*----------------------------------------------------------------
109 Find an address in the hash table;
110 returns a pointer to the mallitem that owns it (or NULL)
111 ------------------------------------------------------------------*/
112
ptr_tracker(void * fred)113 static mallitem * ptr_tracker( void * fred )
114 {
115 int jj,kk ;
116
117 if( fred == NULL ) return NULL ;
118
119 jj = mallkey((char *)fred) % SLOTS ; /* hash table location */
120
121 if( htab[jj] == NULL ) return NULL ; /* nothing there */
122
123 for( kk=0 ; kk < nhtab[jj] ; kk++ ) /* scan for match */
124 if( htab[jj][kk].pmt == fred ) return (htab[jj]+kk) ;
125
126 return NULL ; /* no match found */
127 }
128
129 /*-----------------------------------------------------------------*/
130 /*-- this macro finds an address from the user in the hash table --*/
131
132 #define shift_tracker(fff) ptr_tracker( ((char *)(fff)) - NEXTRA )
133
134 /*-----------------------------------------------------------------
135 Find an empty entry in the hash table list [jj] and return
136 a pointer to it. Will create the entry, if need be.
137 -------------------------------------------------------------------*/
138
find_empty_slot(int jj)139 static mallitem * find_empty_slot( int jj )
140 {
141 int kk ;
142
143 #pragma omp critical (MCW_MALLOC_fes)
144 {
145 if( htab[jj] == NULL ){ /* must make new list */
146 htab[jj] = (mallitem *) malloc(sizeof(mallitem)) ; /* of length 1 at [jj] */
147 nhtab[jj] = 1 ;
148 kk = 0 ;
149 htab[jj][0].pmt = NULL ; /* mark as empty */
150 } else {
151 for( kk=nhtab[jj]-1 ; kk >= 0 ; kk-- ) /* scan (backwards) for NULL entry */
152 if( htab[jj][kk].pmt == NULL ) break ; /* found it? */
153
154 if( kk < 0 ){ /* must make list longer */
155 kk = nhtab[jj] ; nhtab[jj]++ ;
156 htab[jj] = (mallitem *) realloc( htab[jj], sizeof(mallitem)*nhtab[jj] ) ;
157 htab[jj][kk].pmt = NULL ; /* mark as empty */
158 }
159 }
160 } /* end OpenMP critical */
161
162 return (htab[jj]+kk) ;
163 }
164
165 /*----------------------------------------------------------------
166 Add an entry to the hash table, given the
167 address, the user's size, and the filename and line number.
168 ------------------------------------------------------------------*/
169
add_tracker(void * fred,size_t n,char * fn,int ln)170 static void add_tracker( void * fred , size_t n , char * fn , int ln )
171 {
172 int jj ;
173 mallitem *ip ;
174
175 if( fred == NULL ) return ; /* bad news */
176
177 #pragma omp critical (MCW_MALLOC_at)
178 {
179 jj = mallkey((char *)fred) % SLOTS ; /* which hash list to use */
180 ip = find_empty_slot(jj) ; /* get an empty slot in this list */
181
182 /* now put the data into the hash table */
183
184 ip->pmt = fred ;
185 ip->psz = n ;
186 ip->pfn = fn ;
187 ip->pln = ln ;
188 ip->pss = ++serial ;
189
190 ADD_TRACEBACK(ip) ; /* 16 Feb 2001 */
191 } /* end OpenMP critical */
192
193 return ;
194 }
195
196 /*-----------------------------------------------------------------
197 The tracking replacement for malloc
198 -------------------------------------------------------------------*/
199
malloc_track(size_t n,char * fn,int ln)200 static void * malloc_track( size_t n , char *fn , int ln )
201 {
202 char *fred=NULL ;
203
204 #pragma omp critical (MCW_MALLOC_mt)
205 { size_t nn = n + 2*NEXTRA ; int ii ;
206
207 /* fprintf(stderr,"malloc_track(%u,%s,%d)\n",(unsigned int)n,fn,ln) ; */
208
209 fred = (char *) malloc(nn) ;
210 if( fred == NULL ){ /* real bad news */
211 long long val ;
212 fprintf(stderr,
213 "\n*** MCW_malloc(%u) from %s#%d FAILS!\a\n", /* 02 Jan 2002 */
214 (unsigned int)n , fn , ln ) ;
215 val = MCW_MALLOC_total ;
216 if( val > 0 ) fprintf(stderr,"*** current total usage=%lld bytes\n",val);
217 goto IAMDONE ;
218 }
219
220 /* mark overrun buffers */
221
222 for( ii=0 ; ii < NEXTRA ; ii++ )
223 fred[ii] = fred[n+NEXTRA+ii] = MAGIC ;
224
225 add_tracker(fred,n,fn,ln) ; /* put in hash table */
226 IAMDONE: ;
227 } /* end OpenMP critical */
228 if( fred == NULL ) return NULL ;
229 return (void *)(fred+NEXTRA) ;
230 }
231
232 /*-----------------------------------------------------------------
233 Check an entry in the hash table for local overrun integrity
234 -------------------------------------------------------------------*/
235
236 static const char *pr_nam = NULL ;
237 static int pr_lin = 0 ;
238
probe_track(mallitem * ip)239 static void probe_track( mallitem *ip )
240 {
241 int ii ;
242 size_t n ;
243 char *fred ;
244
245 if( ip == NULL ){ pr_nam=NULL; return; } /* error */
246 fred = (char *) ip->pmt ; if( fred == NULL ){ pr_nam=NULL; return; }
247 n = ip->psz ;
248
249 for( ii=0 ; ii < NEXTRA ; ii++ )
250 if( fred[ii] != MAGIC ){
251 fprintf(stderr,"*** MCW_malloc pre-corruption! "
252 "serial=%u size=%u source=%s line#%d",
253 ip->pss,(unsigned int)ip->psz,ip->pfn,ip->pln ) ;
254 #ifdef USE_TRACING
255 { int tt ;
256 for( tt=0 ; tt < NTB && ip->ptb[tt] != NULL ; tt++ )
257 fprintf(stderr," <- %s",ip->ptb[tt]) ;
258 }
259 #endif
260 fprintf(stderr,"\n") ;
261
262 if( pr_nam != NULL )
263 fprintf(stderr," [[ Called from source=%.50s line#%d ]]\n",pr_nam,pr_lin);
264 break ;
265 }
266
267 for( ii=0 ; ii < NEXTRA ; ii++ )
268 if( fred[n+NEXTRA+ii] != MAGIC ){
269 fprintf(stderr,"*** MCW_malloc post-corruption! "
270 "serial=%u size=%u source=%s line#%d\n",
271 ip->pss,(unsigned int)ip->psz,ip->pfn,ip->pln ) ;
272 #ifdef USE_TRACING
273 { int tt ;
274 for( tt=0 ; tt < NTB && ip->ptb[tt] != NULL ; tt++ )
275 fprintf(stderr," <- %s",ip->ptb[tt]) ;
276 }
277 #endif
278 fprintf(stderr,"\n") ;
279
280 if( pr_nam != NULL )
281 fprintf(stderr," [[ Called from source=%.50s line#%d ]]\n",pr_nam,pr_lin);
282 break ;
283 }
284
285 pr_nam = NULL ; /* reset */
286 return ;
287 }
288
289 /*-------------------------------------------------------------------
290 The tracking replacement for realloc
291 ---------------------------------------------------------------------*/
292
realloc_track(mallitem * ip,size_t n,char * fn,int ln)293 static void * realloc_track( mallitem *ip, size_t n, char *fn, int ln )
294 {
295 char *nfred=NULL ;
296
297 if( ip == NULL ) return NULL ; /* should not happen */
298
299 #pragma omp critical (MCW_MALLOC_rt)
300 { char *cfred ;
301 size_t nn = n + 2*NEXTRA ;
302 int ii , cjj,njj , kk ;
303
304 pr_nam = (const char *)fn ; pr_lin = ln ;
305 probe_track(ip) ; /* check for integrity before reallocation */
306 cfred = ip->pmt ; /* old address */
307
308 nfred = (char*)realloc( cfred , nn ) ;
309 if( nfred == NULL ){ /* real bad */
310 long long val ;
311 fprintf(stderr,
312 "\n*** MCW_realloc(%u) from %s#%d FAILS!\a\n", /* 02 Jan 2002 */
313 (unsigned int)n , fn , ln ) ;
314 val = MCW_MALLOC_total ;
315 if( val > 0 ) fprintf(stderr,"*** current total usage=%lld bytes\n",val);
316 goto IAMDONE ;
317 }
318
319 for( ii=0 ; ii < NEXTRA ; ii++ )
320 nfred[ii] = nfred[n+NEXTRA+ii] = MAGIC ;
321
322 cjj = mallkey(cfred) % SLOTS ; /* hash table list for old */
323 njj = mallkey(nfred) % SLOTS ; /* and for new address */
324
325 if( cjj == njj ){ /* can just update old hashtable entry */
326
327 ip->pmt = nfred ;
328 ip->psz = n ;
329 ip->pfn = fn ;
330 ip->pln = ln ;
331 ip->pss = ++serial ;
332
333 ADD_TRACEBACK(ip) ; /* 16 Feb 2001 */
334
335 } else { /* must move into a different list */
336
337 add_tracker( nfred , n , fn , ln ) ;
338
339 ip->pmt = NULL ; /* mark old entry as free */
340 }
341 IAMDONE: ;
342 } /* end OpenMP critical */
343 if( nfred == NULL ) return NULL ;
344 return (void *)(nfred+NEXTRA) ;
345 }
346
347 /*-----------------------------------------------------------------
348 Tracking replacement for calloc
349 -------------------------------------------------------------------*/
350
calloc_track(size_t n,size_t m,char * fn,int ln)351 static void * calloc_track( size_t n , size_t m , char *fn , int ln )
352 {
353 void *fred ;
354 size_t nn = n*m ;
355
356 fred = malloc_track(nn,fn,ln) ; if( fred == NULL ) return NULL ;
357 memset( fred , 0 , nn ) ;
358 return fred ;
359 }
360
361 /*-----------------------------------------------------------------
362 Tracking replacement for free
363 -------------------------------------------------------------------*/
364
free_track(mallitem * ip)365 static void free_track( mallitem *ip )
366 {
367 char *cfred ;
368
369 if( ip == NULL ) return ;
370 cfred = (char *) ip->pmt ;
371 if( cfred == NULL ) return ;
372
373 #pragma omp critical (MCW_MALLOC_ft)
374 {
375 pr_nam = NULL ;
376 probe_track(ip) ; /* check for integrity before freeing */
377 free(cfred) ; ip->pmt = NULL ;
378 } /* end OpenMP critical */
379 return ;
380 }
381
382 /*-----------------------------------------------------------------
383 Return a status line about the situation
384 -------------------------------------------------------------------*/
385
386 static int use_tracking = 0 ; /* is the tracking enabled? */
387
mcw_malloc_status(const char * fn,int ln)388 char * mcw_malloc_status(const char *fn , int ln)
389 {
390 static char buf[128] = "\0" ;
391 if( ! use_tracking ) return NULL ;
392
393 #pragma omp critical (MCW_MALLOC_stat)
394 { int jj,kk , nptr=0 ; long long nbyt=0 ;
395
396 for( jj=0 ; jj < SLOTS ; jj++ ){
397 for( kk=0 ; kk < nhtab[jj] ; kk++ ){
398 if( htab[jj][kk].pmt != NULL ){
399 pr_nam = (const char *)fn ; pr_lin = ln ;
400 probe_track( htab[jj]+kk ) ; /* check for integrity */
401 nptr++ ; nbyt += htab[jj][kk].psz ;
402 }
403 }
404 }
405
406 sprintf(buf,"chunks=%d bytes=%lld",nptr,nbyt) ;
407 } /* end OpenMP critical */
408 return buf ;
409 }
410
411 /*-----------------------------------------------------------------*/
412
mcw_malloc_total(void)413 long long mcw_malloc_total(void) /* 01 Feb 2007 */
414 {
415 long long nbyt=0 ; int jj,kk ;
416
417 if( ! use_tracking ) return 0 ;
418
419 for( jj=0 ; jj < SLOTS ; jj++ )
420 for( kk=0 ; kk < nhtab[jj] ; kk++ )
421 if( htab[jj][kk].pmt != NULL ) nbyt += htab[jj][kk].psz ;
422
423 return nbyt ;
424 }
425
426 /*-----------------------------------------------------------------
427 Write a file with lots of info about the current status
428 -------------------------------------------------------------------*/
429
430 extern int THD_is_file( char * ) ;
431 extern void qsort_intint( int , int * , int * ) ;
432 static int size_sort = 0;
433 void mcw_malloc_dump_fp(FILE *fp) ;
434
435 /** 23 Apr 2015: factor the filename finding and the dumping **/
436
mcw_malloc_dump(void)437 void mcw_malloc_dump(void) /* make up a filename and then call the dumper */
438 {
439 #pragma omp critical (MCW_MALLOC_dump)
440 { int ii ; char fname[32] ; FILE *fp=NULL ;
441 for( ii=1 ; ii < 1000 ; ii++ ){ /* find and open an output file */
442 sprintf(fname,"malldump.%03d",ii) ;
443 if( THD_is_file(fname) ) continue ;
444 fp = fopen( fname , "w" ) ;
445 if( fp == NULL ){
446 fprintf(stderr,"** Unable to open file %s for malloc table dump!\n",fname);
447 goto IAMDONE ;
448 }
449 break ;
450 }
451 if( fp == NULL ){
452 fprintf(stderr,"** Attempt to exceed 999 malloc table dump files!\n") ;
453 goto IAMDONE ;
454 }
455
456 mcw_malloc_dump_fp(fp) ; fclose(fp) ; /* do the work and quit */
457
458 IAMDONE: ; /*nada*/
459 } /* end OpenMP critical */
460
461 return ;
462 }
463
464 /*------------------------------------------------------------------*/
465 /* 23 Apr 2015: do the dumping to an already open file (left open) */
466
mcw_malloc_dump_fp(FILE * fp)467 void mcw_malloc_dump_fp(FILE *fp)
468 {
469 if( ! use_tracking || fp == NULL ) return ;
470
471 #pragma omp critical (MCW_MALLOC_dumpfp)
472 { int ii,jj,kk,nptr=0 ; char *str ; int *ss , *jk ;
473
474 /* count number of entries in the hash table */
475
476 for( jj=0 ; jj < SLOTS ; jj++ ){
477 for( kk=0 ; kk < nhtab[jj] ; kk++ ){
478 if( htab[jj][kk].pmt != NULL ) nptr++ ;
479 }
480 }
481
482 fprintf(fp,".....................................................................\n");
483 fprintf(fp,".................... mcw_malloc() tracking table ....................\n");
484 if( nptr < 1 ){
485 fprintf(fp ,"--- Nothing is malloc()-ed !? ---\n") ;
486 fprintf(stderr,"--- Nothing is malloc()-ed !? ---\n") ;
487 goto IAMDONE ;
488 }
489
490 /* setup to sort by serial number */
491
492 ss = (int *) malloc(sizeof(int)*nptr) ; /* serial number */
493 jk = (int *) malloc(sizeof(int)*nptr) ; /* holds combination of jj and kk */
494
495 #define JBASE 32768 /* JBASE * SLOTS must be less than max int */
496
497 /* scan table for non-NULL entries */
498
499 for( ii=jj=0 ; jj < SLOTS ; jj++ ){
500 for( kk=0 ; kk < nhtab[jj] ; kk++ ){
501 if( htab[jj][kk].pmt != NULL ){
502 if (size_sort) ss[ii] = htab[jj][kk].psz ; /* save size */
503 else ss[ii] = htab[jj][kk].pss ; /* save serial number */
504 jk[ii] = JBASE*jj + kk ; /* save jj and kk */
505 ii++ ;
506 }
507 }
508 }
509
510 qsort_intint( nptr , ss , jk ) ; /* sort by ss, carrying jk along */
511
512 /* now print table in serial number order */
513
514 #ifdef USE_TRACING
515 fprintf(fp, "MCW Malloc Table Dump:\n"
516 "serial# size source file line# address hash(j,k) <- Called by\n"
517 "------- ---------- -------------------- ----- ---------- ----- --- ---------\n");
518 #else
519 fprintf(fp, "MCW Malloc Table Dump:\n"
520 "serial# size source file line# address hash(j,k)\n"
521 "------- ---------- -------------------- ----- ---------- ----- ---\n") ;
522 #endif
523
524 for( ii=0 ; ii < nptr ; ii++ ){
525 jj = jk[ii] / JBASE ; /* retrieve jj and kk */
526 kk = jk[ii] % JBASE ;
527 if( htab[jj][kk].pmt != NULL ){
528 fprintf(fp,"%7u %10d %-20.30s %5d %10p %5d %3d",
529 htab[jj][kk].pss , (int)htab[jj][kk].psz ,
530 htab[jj][kk].pfn , htab[jj][kk].pln , htab[jj][kk].pmt ,
531 jj,kk ) ;
532 #ifdef USE_TRACING
533 { int tt ;
534 for( tt=0 ; tt < NTB && htab[jj][kk].ptb[tt] != NULL ; tt++ )
535 fprintf(fp," <- %s",htab[jj][kk].ptb[tt]) ;
536 }
537 #endif
538 fprintf(fp,"\n") ;
539 }
540 else
541 fprintf(fp,"*** Error at ii=%d jj=%d kk=%d\n",ii,jj,kk) ;
542 }
543
544 free(ss) ; free(jk) ;
545
546 /* and print out the summary line (to the file) */
547
548 str = mcw_malloc_status(NULL,0) ;
549 fprintf(fp,"----- Summary: %s\n",str) ;
550
551 if( fp != stderr ){
552 fprintf(stderr,"** Malloc table dumped to output file\n") ;
553 fprintf(stderr,"** Summary: %s\n",str) ;
554 }
555
556 IAMDONE:
557 fprintf(fp,".....................................................................\n");
558 } /* end OpenMP critical */
559
560 return ;
561 }
562
563 /*--------------------------------------------------------------------*/
564 /* put below mcw_malloc_dump to appease solaris 30 Dec 2013 [rickr] */
565
mcw_malloc_dump_sort(int opt)566 void mcw_malloc_dump_sort(int opt) {
567 if (opt == 1) size_sort = 1;
568 mcw_malloc_dump();
569 if (opt == 1) size_sort = 0;
570 }
571
572 /*----------------------------------------------------------------
573 Turn on use of the tracking routines
574 ------------------------------------------------------------------*/
575
enable_mcw_malloc()576 void enable_mcw_malloc() /* cannot be disabled */
577 {
578 char *str = getenv("AFNI_NO_MCW_MALLOC") ; /* NOT my_getenv */
579
580 #pragma omp critical (MCW_MALLOC_emm)
581 {
582 if( use_tracking ) goto IAMDONE ;
583 use_tracking = 1 ;
584 if( str!=NULL && ( str[0]=='y' || str[0]=='Y') ) use_tracking = 0 ;
585
586 if( use_tracking && htab == NULL ){ /* initialize hash table */
587 int jj ;
588 htab = (mallitem **) malloc( SLOTS * sizeof(mallitem *) ) ;
589 nhtab = (int *) malloc( SLOTS * sizeof(int) ) ;
590 for( jj=0 ; jj < SLOTS ; jj++ ){
591 htab[jj] = NULL ; nhtab[jj] = 0 ;
592 }
593 }
594 IAMDONE: ;
595 } /* end OpenMP critical */
596 return ;
597 }
598
599 /* ---------------------------------------
600 Force a halt to memory tracking.
601 the halt is meant to be temporary.
602 Had to add this for SUMA to get around
603 the problem of using allocate2D with
604 large numbers of pointers. ZSS 03/04
605 --------------------------------------- */
606 static int pz = 0; /* flag to indicate pause */
pause_mcw_malloc()607 void pause_mcw_malloc()
608 {
609 #pragma omp critical (MCW_MALLOC_pmm)
610 {
611 if (!pz && use_tracking) {
612 pz = 1; use_tracking = 0;
613 }
614 } /* end OpenMP critical */
615 return;
616 }
resume_mcw_malloc()617 void resume_mcw_malloc()
618 {
619 #pragma omp critical (MCW_MALLOC_rmm)
620 {
621 if( pz ){
622 pz = 0; use_tracking = 1;
623 }
624 } /* end OpenMP critical */
625 return;
626 }
mcw_malloc_paused()627 int mcw_malloc_paused()
628 {
629 return(pz);
630 }
631
632 /*---------------------------------------------------------------*/
633 /*--- lets the user check if the tracking routines are in use ---*/
634
mcw_malloc_enabled(void)635 int mcw_malloc_enabled(void){ return (use_tracking != 0) ; }
636
637 /*-----------------------------------------------------------------
638 The actual routine that replaces malloc() -- see mcw_malloc.h
639 -------------------------------------------------------------------*/
640
mcw_malloc(size_t n,char * fnam,int lnum)641 void * mcw_malloc( size_t n , char *fnam , int lnum )
642 {
643 if( use_tracking ) return malloc_track(n,fnam,lnum) ;
644 else return malloc(n) ;
645 }
646
647 /*----------------------------------------------------------------
648 The actual replacement for realloc()
649 ------------------------------------------------------------------*/
650
mcw_realloc(void * fred,size_t n,char * fnam,int lnum)651 void * mcw_realloc( void *fred , size_t n , char *fnam , int lnum )
652 {
653 mallitem *ip ;
654
655 if( fred == NULL )
656 return mcw_malloc( n , fnam , lnum ) ;
657
658 if( use_tracking && (ip=shift_tracker(fred)) != NULL )
659 return realloc_track( ip , n , fnam,lnum ) ;
660 else {
661 #ifdef USE_TRACING
662 if( use_tracking ){
663 char buf[1024] ;
664 sprintf(buf,"** realloc() of non-tracked pointer [%s line %d] ??",fnam,lnum) ;
665 STATUS(buf) ;
666 }
667 #endif
668 return realloc( fred , n ) ;
669 }
670 }
671
672 /*----------------------------------------------------------------
673 The actual replacement for calloc()
674 ------------------------------------------------------------------*/
675
mcw_calloc(size_t n,size_t m,char * fnam,int lnum)676 void * mcw_calloc( size_t n , size_t m , char *fnam , int lnum )
677 {
678 if( use_tracking ) return calloc_track( n , m , fnam,lnum ) ;
679 else return calloc( n , m ) ;
680 }
681
682 /*-----------------------------------------------------------------
683 Replacement for strdup() [06 May 2015]
684 -------------------------------------------------------------------*/
685
mcw_strdup(char * ssin,char * fnam,int lnum)686 char * mcw_strdup( char *ssin , char *fnam , int lnum )
687 {
688 char *ssout = NULL ; size_t lss ;
689
690 if( ssin == NULL ) return ssout ; /* stupid (ab)user */
691
692 lss = strlen(ssin)+1 ;
693 if( use_tracking ){
694 ssout = mcw_malloc( lss , fnam,lnum ) ;
695 #if 0
696 { char buf[1024]; sprintf(buf,"called mcw_strdup() [%s line %d p=%p]",fnam,lnum,ssout); STATUS(buf); }
697 #endif
698 } else {
699 ssout = malloc(lss) ;
700 }
701 strcpy(ssout,ssin) ;
702 return ssout ;
703 }
704
705 #ifndef DONT_USE_MCW_MALLOC
706 /*-----------------------------------------------------------------
707 Is this pointer OK?
708 -------------------------------------------------------------------*/
709
mcw_malloc_OK(void * fred)710 int mcw_malloc_OK( void *fred )
711 {
712 mallitem *ip ;
713 if( fred == NULL || !use_tracking ) return 1 ;
714 ip = shift_tracker(fred) ;
715 return (ip != NULL) ;
716 }
717 #endif
718
719 /*-----------------------------------------------------------------
720 The actual replacment for free()
721 -------------------------------------------------------------------*/
722
mcw_free(void * fred,char * fnam,int lnum)723 void mcw_free( void *fred , char *fnam , int lnum )
724 {
725 mallitem *ip ;
726
727 if( fred == NULL ) return ;
728 if( use_tracking && (ip=shift_tracker(fred)) != NULL ){
729 /* fprintf(stderr,"mcw_free(%s,%d) -- from %s,%d\n",fnam,lnum,ip->pfn,ip->pln) ; */
730 free_track( ip ) ;
731 } else {
732 #ifdef USE_TRACING
733 if( use_tracking ){
734 char buf[1024] ;
735 sprintf(buf,"** free() of non-tracked pointer [%s line %d] ??",fnam,lnum) ;
736 STATUS(buf) ;
737 }
738 #endif
739 free( fred ) ;
740 }
741 }
742
743 /*-----------------------------------------------------------------
744 The actual replacement for XtMalloc()
745 -------------------------------------------------------------------*/
746
mcw_XtMalloc(RwcCardinal n,char * fnam,int lnum)747 char * mcw_XtMalloc( RwcCardinal n , char *fnam , int lnum )
748 {
749 if( use_tracking ) return (char *)malloc_track(n,fnam,lnum) ;
750 else return (char *)RwcMalloc(n) ;
751 }
752
753 /*-----------------------------------------------------------------
754 The actual replacement for XtRealloc()
755 -------------------------------------------------------------------*/
756
mcw_XtRealloc(char * p,RwcCardinal n,char * fnam,int lnum)757 char * mcw_XtRealloc( char *p, RwcCardinal n , char *fnam , int lnum )
758 {
759 mallitem *ip ;
760
761 if( p == NULL )
762 return mcw_XtMalloc( n , fnam , lnum ) ;
763
764 if( use_tracking && (ip=shift_tracker(p)) != NULL )
765 return (char*)realloc_track( ip , n , fnam,lnum ) ;
766 else
767 return (char*)RwcRealloc( p , n ) ;
768 }
769
770 /*----------------------------------------------------------------
771 The actual replacement for XtFree()
772 ------------------------------------------------------------------*/
773
mcw_XtFree(char * p)774 void mcw_XtFree( char *p )
775 {
776 mallitem *ip ;
777
778 if( p == NULL ) return ;
779 if( use_tracking && (ip=shift_tracker(p)) != NULL ) free_track(ip) ;
780 else {
781 #ifdef USE_TRACING
782 if( use_tracking ){
783 char buf[1024] ;
784 sprintf(buf,"** XtFree() of non-tracked pointer ??") ;
785 STATUS(buf) ;
786 }
787 #endif
788 RwcFree(p) ;
789 }
790 }
791
792 /*-----------------------------------------------------------------
793 The actual replacement for XtCalloc()
794 -------------------------------------------------------------------*/
795
mcw_XtCalloc(RwcCardinal n,RwcCardinal m,char * fnam,int lnum)796 char * mcw_XtCalloc( RwcCardinal n , RwcCardinal m , char *fnam , int lnum )
797 {
798 if( use_tracking ) return (char *) calloc_track( n , m , fnam,lnum ) ;
799 else return RwcCalloc( n , m ) ;
800 }
801
802 #else /* just something, anything [fake functions] */
803
mcw_malloc_total(void)804 long long mcw_malloc_total(void){ return 0 ; }
pause_mcw_malloc()805 void pause_mcw_malloc() { return ; }
resume_mcw_malloc()806 void resume_mcw_malloc() { return ; }
mcw_malloc_enabled()807 int mcw_malloc_enabled() { return 0 ; }
mcw_malloc_dump_sort()808 void mcw_malloc_dump_sort() { return ; }
mcw_malloc_dump()809 void mcw_malloc_dump() { return ; }
enable_mcw_malloc()810 void enable_mcw_malloc() { return ; }
mcw_malloc_status()811 char * mcw_malloc_status() { return (char *)0 ; }
812
813 #endif
814