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