CGEM BOSS 6.6.5.h
BESIII Offline Software System
Loading...
Searching...
No Matches
KalFitMemLeak.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>
#include <time.h>
#include <limits.h>
#include "memwatch.h"
#include <ctype.h>

Go to the source code of this file.

Classes

struct  mwData_
 
struct  mwStat_
 
struct  mwGrabData_
 
struct  mwMarker_
 

Macros

#define __MEMWATCH_C   1
 
#define VERSION   "2.71" /* the current version number */
 
#define CHKVAL(mw)
 
#define FLUSH()
 
#define TESTS(f, l)
 
#define PRECHK   0x01234567L
 
#define POSTCHK   0x76543210L
 
#define mwBUFFER_TO_MW(p)
 
#define MW_NML   0x0001
 
#define COMMIT   "" /* Normal ANSI */
 
#define CPPTEXT   ""
 
#define mwSTDERR   mwLog
 
#define MW_MUTEX_INIT()
 
#define MW_MUTEX_TERM()
 
#define MW_MUTEX_LOCK()
 
#define MW_MUTEX_UNLOCK()
 
#define mw16BIT   1
 
#define mwROUNDALLOC_DEFAULT   2
 
#define mwROUNDALLOC   mwROUNDALLOC_DEFAULT
 
#define AIPH()
 

Typedefs

typedef struct mwData_ mwData
 
typedef struct mwStat_ mwStat
 
typedef struct mwGrabData_ mwGrabData
 
typedef struct mwMarker_ mwMarker
 

Functions

void mwInit (void)
 
void mwAbort (void)
 
void mwTerm (void)
 
void mwStatistics (int level)
 
void mwAutoCheck (int onoff)
 
void mwSetOutFunc (void(*func)(int))
 
int mwTest (const char *file, int line, int items)
 
int mwTestBuffer (const char *file, int line, void *p)
 
void mwBreakOut (const char *cause)
 
void * mwMark (void *p, const char *desc, const char *file, unsigned line)
 
void * mwUnmark (void *p, const char *file, unsigned line)
 
int mwAriHandler (const char *estr)
 
void mwSetAriFunc (int(*func)(const char *))
 
void * mwMalloc (size_t size, const char *file, int line)
 
void * mwRealloc (void *p, size_t size, const char *file, int line)
 
char * mwStrdup (const char *str, const char *file, int line)
 
void mwFree (void *p, const char *file, int line)
 
void * mwCalloc (size_t a, size_t b, const char *file, int line)
 
void mwFree_ (void *p)
 
void * mwMalloc_ (size_t size)
 
void * mwRealloc_ (void *p, size_t size)
 
void * mwCalloc_ (size_t a, size_t b)
 
void mwFlushNow (void)
 
void mwDoFlush (int onoff)
 
void mwLimit (long lim)
 
void mwSetAriAction (int action)
 
int mwAssert (int exp, const char *exps, const char *fn, int ln)
 
int mwVerify (int exp, const char *exps, const char *fn, int ln)
 
void mwTrace (const char *format,...)
 
unsigned mwGrab (unsigned kb)
 
unsigned mwDrop (unsigned kb)
 
void mwNoMansLand (int level)
 
int mwIsReadAddr (const void *p, unsigned len)
 
int mwIsSafeAddr (void *p, unsigned len)
 

Macro Definition Documentation

◆ __MEMWATCH_C

#define __MEMWATCH_C   1

Definition at line 97 of file KalFitMemLeak.c.

◆ AIPH

#define AIPH ( )
Value:
if( always_invoked ) { mwWrite("autocheck: <%ld> %s(%d) ", mwCounter, file, line ); always_invoked = 0; }

Definition at line 2152 of file KalFitMemLeak.c.

◆ CHKVAL

#define CHKVAL ( mw)
Value:
(0xFE0180L^(long)mw->count^(long)mw->size^(long)mw->line)

Definition at line 140 of file KalFitMemLeak.c.

Referenced by mwMalloc().

◆ COMMIT

#define COMMIT   "" /* Normal ANSI */

Definition at line 153 of file KalFitMemLeak.c.

◆ CPPTEXT

#define CPPTEXT   ""

Definition at line 159 of file KalFitMemLeak.c.

Referenced by mwInit().

◆ FLUSH

#define FLUSH ( )
Value:
mwFlush()

Definition at line 141 of file KalFitMemLeak.c.

Referenced by mwAbort(), mwAssert(), mwFree(), mwInit(), mwLimit(), mwMalloc(), mwRealloc(), mwStrdup(), mwTrace(), and mwVerify().

◆ mw16BIT

#define mw16BIT   1

Definition at line 199 of file KalFitMemLeak.c.

◆ MW_MUTEX_INIT

#define MW_MUTEX_INIT ( )

Definition at line 174 of file KalFitMemLeak.c.

Referenced by mwInit().

◆ MW_MUTEX_LOCK

#define MW_MUTEX_LOCK ( )

◆ MW_MUTEX_TERM

#define MW_MUTEX_TERM ( )

Definition at line 175 of file KalFitMemLeak.c.

Referenced by mwAbort().

◆ MW_MUTEX_UNLOCK

#define MW_MUTEX_UNLOCK ( )

◆ MW_NML

#define MW_NML   0x0001

Definition at line 148 of file KalFitMemLeak.c.

Referenced by mwAbort(), mwFree(), and mwRealloc().

◆ mwBUFFER_TO_MW

#define mwBUFFER_TO_MW ( p)
Value:
( (mwData*) (void*) ( ((char*)p)-mwDataSize-mwOverflowZoneSize ) )

Definition at line 145 of file KalFitMemLeak.c.

Referenced by mwFree(), mwRealloc(), and mwTestBuffer().

◆ mwROUNDALLOC

#define mwROUNDALLOC   mwROUNDALLOC_DEFAULT

Definition at line 217 of file KalFitMemLeak.c.

Referenced by mwFree(), and mwInit().

◆ mwROUNDALLOC_DEFAULT

#define mwROUNDALLOC_DEFAULT   2

Definition at line 200 of file KalFitMemLeak.c.

◆ mwSTDERR

#define mwSTDERR   mwLog

Definition at line 165 of file KalFitMemLeak.c.

Referenced by mwAbort(), mwAssert(), mwBreakOut(), and mwVerify().

◆ POSTCHK

#define POSTCHK   0x76543210L

Definition at line 144 of file KalFitMemLeak.c.

◆ PRECHK

#define PRECHK   0x01234567L

Definition at line 143 of file KalFitMemLeak.c.

◆ TESTS

#define TESTS ( f,
l )
Value:
if(mwTestAlways) (void)mwTestNow(f,l,1)

Definition at line 142 of file KalFitMemLeak.c.

Referenced by mwAssert(), mwCalloc_(), mwDrop(), mwFree(), mwFree_(), mwGrab(), mwLimit(), mwMalloc(), mwMalloc_(), mwMark(), mwNoMansLand(), mwRealloc(), mwRealloc_(), mwSetAriAction(), mwTrace(), and mwVerify().

◆ VERSION

#define VERSION   "2.71" /* the current version number */

Definition at line 139 of file KalFitMemLeak.c.

Referenced by mwInit().

Typedef Documentation

◆ mwData

typedef struct mwData_ mwData

Definition at line 254 of file KalFitMemLeak.c.

◆ mwGrabData

typedef struct mwGrabData_ mwGrabData

Definition at line 282 of file KalFitMemLeak.c.

◆ mwMarker

typedef struct mwMarker_ mwMarker

Definition at line 289 of file KalFitMemLeak.c.

◆ mwStat

typedef struct mwStat_ mwStat

Definition at line 270 of file KalFitMemLeak.c.

Function Documentation

◆ mwAbort()

void mwAbort ( void )

Definition at line 517 of file KalFitMemLeak.c.

517 {
518 mwData *mw;
519 mwMarker *mrk;
520 char *data;
521 time_t tid;
522 int c, i, j;
523 int errors;
524
525 tid = time( NULL );
526 mwWrite( "\nStopped at %s\n", ctime( &tid) );
527
528 if( !mwInited )
529 mwWrite( "internal: mwAbort(): MEMWATCH not initialized!\n" );
530
531 /* release the grab list */
532 mwDropAll();
533
534 /* report mwMarked items */
535 while( mwFirstMark ) {
536 mrk = mwFirstMark->next;
537 mwWrite( "mark: %p: %s\n", mwFirstMark->host, mwFirstMark->text );
538 free( mwFirstMark->text );
539 free( mwFirstMark );
540 mwFirstMark = mrk;
541 mwErrors ++;
542 }
543
544 /* release all still allocated memory */
545 errors = 0;
546 while( mwHead != NULL && errors < 3 ) {
547 if( !mwIsOwned(mwHead, __FILE__, __LINE__ ) ) {
548 if( errors < 3 )
549 {
550 errors ++;
551 mwWrite( "internal: NML/unfreed scan restarting\n" );
552 FLUSH();
553 mwHead = mwHead;
554 continue;
555 }
556 mwWrite( "internal: NML/unfreed scan aborted, heap too damaged\n" );
557 FLUSH();
558 break;
559 }
560 mwFlushW(0);
561 if( !(mwHead->flag & MW_NML) ) {
562 mwErrors++;
563 data = ((char*)mwHead)+mwDataSize;
564 mwWrite( "unfreed: <%ld> %s(%d), %ld bytes at %p ",
565 mwHead->count, mwHead->file, mwHead->line, (long)mwHead->size, data+mwOverflowZoneSize );
566 if( mwCheckOF( data ) ) {
567 mwWrite( "[underflowed] ");
568 FLUSH();
569 }
570 if( mwCheckOF( (data+mwOverflowZoneSize+mwHead->size) ) ) {
571 mwWrite( "[overflowed] ");
572 FLUSH();
573 }
574 mwWrite( " \t{" );
575 j = 16; if( mwHead->size < 16 ) j = (int) mwHead->size;
576 for( i=0;i<16;i++ ) {
577 if( i<j ) mwWrite( "%02X ",
578 (unsigned char) *(data+mwOverflowZoneSize+i) );
579 else mwWrite( ".. " );
580 }
581 for( i=0;i<j;i++ ) {
582 c = *(data+mwOverflowZoneSize+i);
583 if( c < 32 || c > 126 ) c = '.';
584 mwWrite( "%c", c );
585 }
586 mwWrite( "}\n" );
587 mw = mwHead;
588 mwUnlink( mw, __FILE__, __LINE__ );
589 free( mw );
590 }
591 else {
592 data = ((char*)mwHead) + mwDataSize + mwOverflowZoneSize;
593 if( mwTestMem( data, mwHead->size, MW_VAL_NML ) ) {
594 mwErrors++;
595 mwWrite( "wild pointer: <%ld> NoMansLand %p alloc'd at %s(%d)\n",
596 mwHead->count, data + mwOverflowZoneSize, mwHead->file, mwHead->line );
597 FLUSH();
598 }
599 mwNmlNumAlloc --;
600 mwNmlCurAlloc -= mwHead->size;
601 mw = mwHead;
602 mwUnlink( mw, __FILE__, __LINE__ );
603 free( mw );
604 }
605 }
606
607 if( mwNmlNumAlloc ) mwWrite("internal: NoMansLand block counter %ld, not zero\n", mwNmlNumAlloc );
608 if( mwNmlCurAlloc ) mwWrite("internal: NoMansLand byte counter %ld, not zero\n", mwNmlCurAlloc );
609
610 /* report statistics */
611 mwStatReport();
612 FLUSH();
613
614 mwInited = 0;
615 mwHead = mwTail = NULL;
616 if( mwErrors )
617 fprintf(mwSTDERR,"MEMWATCH detected %ld anomalies\n",mwErrors);
618 mwLogFile( NULL );
619 mwErrors = 0;
620
622
623 }
TTree * data
Double_t time
#define MW_NML
#define MW_MUTEX_TERM()
#define mwSTDERR
#define FLUSH()
#define MW_VAL_NML
size_t size
const char * file
unsigned flag
mwMarker * next

Referenced by mwInit(), and mwTerm().

◆ mwAriHandler()

int mwAriHandler ( const char * estr)

Definition at line 848 of file KalFitMemLeak.c.

848 {
849 mwAutoInit();
850 return mwARI( estr );
851 }

◆ mwAssert()

int mwAssert ( int exp,
const char * exps,
const char * fn,
int ln )

Definition at line 1228 of file KalFitMemLeak.c.

1228 {
1229 int i;
1230 char buffer[MW_TRACE_BUFFER+8];
1231 if( exp ) {
1232 return 0;
1233 }
1234 mwAutoInit();
1235 MW_MUTEX_LOCK();
1236 TESTS(fn,ln);
1237 mwIncErr();
1238 mwCounter++;
1239 mwWrite( "assert trap: <%ld> %s(%d), %s\n", mwCounter, fn, ln, exps );
1240 if( mwAriFunction != NULL ) {
1241 sprintf( buffer, "MEMWATCH: assert trap: %s(%d), %s", fn, ln, exps );
1242 i = (*mwAriFunction)(buffer);
1243 switch( i ) {
1244 case MW_ARI_IGNORE:
1245 mwWrite( "assert trap: <%ld> IGNORED - execution continues\n", mwCounter );
1247 return 0;
1248 case MW_ARI_RETRY:
1249 mwWrite( "assert trap: <%ld> RETRY - executing again\n", mwCounter );
1251 return 1;
1252 }
1253 }
1254 else {
1255 if( mwAriAction & MW_ARI_IGNORE ) {
1256 mwWrite( "assert trap: <%ld> AUTO IGNORED - execution continues\n", mwCounter );
1258 return 0;
1259 }
1260 fprintf(mwSTDERR,"\nMEMWATCH: assert trap: %s(%d), %s\n", fn, ln, exps );
1261 }
1262
1263 FLUSH();
1264 (void) mwTestNow( fn, ln, 1 );
1265 FLUSH();
1266
1267 if( mwAriAction & MW_ARI_NULLREAD ) {
1268 /* This is made in an attempt to kick in */
1269 /* any debuggers or OS stack traces */
1270 FLUSH();
1271 /*lint -save -e413 */
1272 i = *((int*)NULL);
1273 mwDummy( (char)i );
1274 /*lint -restore */
1275 }
1276
1278 exit(255);
1279 /* NOT REACHED - the return statement is in to keep */
1280 /* stupid compilers from squeaking about differing return modes. */
1281 /* Smart compilers instead say 'code unreachable...' */
1282 /*lint -save -e527 */
1283 return 0;
1284 /*lint -restore */
1285 }
EvtComplex exp(const EvtComplex &c)
#define MW_MUTEX_UNLOCK()
#define TESTS(f, l)
#define MW_MUTEX_LOCK()
#define MW_ARI_RETRY
#define MW_ARI_IGNORE
#define MW_TRACE_BUFFER
#define MW_ARI_NULLREAD
const unsigned long mwCounter

◆ mwAutoCheck()

void mwAutoCheck ( int onoff)

Definition at line 649 of file KalFitMemLeak.c.

649 {
650 mwAutoInit();
651 mwTestAlways = onoff;
652 if( onoff ) mwTestFlags = MW_TEST_ALL;
653 }
#define MW_TEST_ALL

◆ mwBreakOut()

void mwBreakOut ( const char * cause)

Definition at line 709 of file KalFitMemLeak.c.

709 {
710 fprintf(mwSTDERR, "breakout: %s\n", cause);
711 mwWrite("breakout: %s\n", cause );
712 return;
713 }

◆ mwCalloc()

void * mwCalloc ( size_t a,
size_t b,
const char * file,
int line )

Definition at line 1154 of file KalFitMemLeak.c.

1154 {
1155 void *p;
1156 size_t size = a * b;
1157 p = mwMalloc( size, file, line );
1158 if( p == NULL ) return NULL;
1159 memset( p, 0, size );
1160 return p;
1161 }
#define mwMalloc(n, f, l)

◆ mwCalloc_()

void * mwCalloc_ ( size_t a,
size_t b )

Definition at line 1184 of file KalFitMemLeak.c.

1184 {
1185 MW_MUTEX_LOCK();
1186 TESTS(NULL,0);
1188 return calloc( a, b );
1189 }

◆ mwDoFlush()

void mwDoFlush ( int onoff)

Definition at line 1196 of file KalFitMemLeak.c.

1196 {
1197 mwFlushW( onoff<1?0:onoff );
1198 if( onoff ) if( mwLogR() ) fflush( mwLogR() );
1199 return;
1200 }

◆ mwDrop()

unsigned mwDrop ( unsigned kb)

Definition at line 1377 of file KalFitMemLeak.c.

1377 {
1378 TESTS(NULL,0);
1379 return mwDrop_( kb, MW_VAL_GRB, 0 );
1380 }
#define MW_VAL_GRB

◆ mwFlushNow()

void mwFlushNow ( void )

Definition at line 1191 of file KalFitMemLeak.c.

1191 {
1192 if( mwLogR() ) fflush( mwLogR() );
1193 return;
1194 }

◆ mwFree()

void mwFree ( void * p,
const char * file,
int line )

Definition at line 1051 of file KalFitMemLeak.c.

1051 {
1052 int i;
1053 mwData* mw;
1054 char buffer[ sizeof(mwData) + (mwROUNDALLOC*3) + 64 ];
1055
1056 /* this code is in support of C++ delete */
1057 if( file == NULL ) {
1058 mwFree_( p );
1060 return;
1061 }
1062
1063 mwAutoInit();
1064
1065 MW_MUTEX_LOCK();
1066 TESTS(file,line);
1067 mwCounter ++;
1068
1069 /* on NULL free, write a warning and return */
1070 if( p == NULL ) {
1071 mwWrite( "NULL free: <%ld> %s(%d), NULL pointer free'd\n",
1072 mwCounter, file, line );
1073 FLUSH();
1075 return;
1076 }
1077
1078 /* do the quick ownership test */
1079 mw = (mwData*) mwBUFFER_TO_MW( p );
1080
1081 if( mwIsOwned( mw, file, line ) ) {
1082 (void) mwTestBuf( mw, file, line );
1083
1084 /* if the buffer is an NML, treat this as a double-free */
1085 if( mw->flag & MW_NML )
1086 {
1087 if( *(((unsigned char*)mw)+mwDataSize+mwOverflowZoneSize) != MW_VAL_NML )
1088 {
1089 mwWrite( "internal: <%ld> %s(%d), no-mans-land MW-%p is corrupted\n",
1090 mwCounter, file, line, mw );
1091 }
1092 goto check_dbl_free;
1093 }
1094
1095 /* update the statistics */
1096 mwNumCurAlloc --;
1097 mwStatCurAlloc -= (long) mw->size;
1098 if( mwStatLevel ) mwStatFree( mw->size, mw->file, mw->line );
1099
1100 /* we should either free the allocation or keep it as NML */
1101 if( mwNML ) {
1102 mw->flag |= MW_NML;
1103 mwNmlNumAlloc ++;
1104 mwNmlCurAlloc += (long) mw->size;
1105 memset( ((char*)mw)+mwDataSize+mwOverflowZoneSize, MW_VAL_NML, mw->size );
1106 }
1107 else {
1108 /* unlink the allocation, and enter the post-free data */
1109 mwUnlink( mw, file, line );
1110 memset( mw, MW_VAL_DEL,
1111 mw->size + mwDataSize+mwOverflowZoneSize+mwOverflowZoneSize );
1112 if( mwFBI ) {
1113 memset( mw, '.', mwDataSize + mwOverflowZoneSize );
1114 sprintf( buffer, "FBI<%ld>%s(%d)", mwCounter, file, line );
1115 strncpy( (char*)(void*)mw, buffer, mwDataSize + mwOverflowZoneSize );
1116 }
1117 free( mw );
1118 }
1119
1120 /* add the pointer to the last-free track */
1121 mwLFfile[ mwLFcur ] = file;
1122 mwLFline[ mwLFcur ] = line;
1123 mwLastFree[ mwLFcur++ ] = p;
1124 if( mwLFcur == MW_FREE_LIST ) mwLFcur = 0;
1125
1127 return;
1128 }
1129
1130 /* check for double-freeing */
1131check_dbl_free:
1132 for(i=0;i<MW_FREE_LIST;i++) {
1133 if( mwLastFree[i] == p ) {
1134 mwIncErr();
1135 mwWrite( "double-free: <%ld> %s(%d), %p was"
1136 " freed from %s(%d)\n",
1137 mwCounter, file, line, p,
1138 mwLFfile[i], mwLFline[i] );
1139 FLUSH();
1141 return;
1142 }
1143 }
1144
1145 /* some weird pointer... block the free */
1146 mwIncErr();
1147 mwWrite( "WILD free: <%ld> %s(%d), unknown pointer %p\n",
1148 mwCounter, file, line, p );
1149 FLUSH();
1151 return;
1152 }
#define mwBUFFER_TO_MW(p)
#define mwROUNDALLOC
struct mwData_ mwData
#define mwFree_(p)
#define MW_FREE_LIST
#define MW_VAL_DEL

◆ mwFree_()

void mwFree_ ( void * p)

Definition at line 1163 of file KalFitMemLeak.c.

1163 {
1164 MW_MUTEX_LOCK();
1165 TESTS(NULL,0);
1167 free(p);
1168 }

◆ mwGrab()

unsigned mwGrab ( unsigned kb)

Definition at line 1372 of file KalFitMemLeak.c.

1372 {
1373 TESTS(NULL,0);
1374 return mwGrab_( kb, MW_VAL_GRB, 0 );
1375 }

◆ mwInit()

void mwInit ( void )

Definition at line 413 of file KalFitMemLeak.c.

413 {
414 time_t tid;
415
416 if( mwInited++ > 0 ) return;
417
419
420 /* start a log if none is running */
421 if( mwLogR() == NULL ) mwLogFile( "memwatch.log" );
422 if( mwLogR() == NULL ) {
423 int i;
424 char buf[32];
425 /* oops, could not open it! */
426 /* probably because it's already open */
427 /* so we try some other names */
428 for( i=1; i<100; i++ ) {
429 sprintf( buf, "memwat%02d.log", i );
430 mwLogFile( buf );
431 if( mwLogR() != NULL ) break;
432 }
433 }
434
435 /* initialize the statistics */
436 mwStatList = NULL;
437 mwStatTotAlloc = 0L;
438 mwStatCurAlloc = 0L;
439 mwStatMaxAlloc = 0L;
440 mwStatNumAlloc = 0L;
441 mwNmlCurAlloc = 0L;
442 mwNmlNumAlloc = 0L;
443
444 /* calculate the buffer size to use for a mwData */
445 mwDataSize = sizeof(mwData);
446 while( mwDataSize % mwROUNDALLOC ) mwDataSize ++;
447
448 /* write informational header if needed */
449 if( !mwInfoWritten ) {
450 mwInfoWritten = 1;
451 (void) time( &tid );
452 mwWrite(
453 "\n============="
454 " MEMWATCH " VERSION " Copyright (C) 1992-1999 Johan Lindh "
455 "=============\n");
456 mwWrite( "\nStarted at %s\n", ctime( &tid ) );
457
458/**************************************************************** Generic */
459 mwWrite( "Modes: " );
460#ifdef mwNew
461 mwWrite( "C++ " );
462#endif /* mwNew */
463#ifdef __STDC__
464 mwWrite( "__STDC__ " );
465#endif /* __STDC__ */
466#ifdef mw16BIT
467 mwWrite( "16-bit " );
468#endif
469#ifdef mw32BIT
470 mwWrite( "32-bit " );
471#endif
472#ifdef mw64BIT
473 mwWrite( "64-bit " );
474#endif
475 mwWrite( "mwDWORD==(" mwDWORD_DEFINED ")\n" );
476 mwWrite( "mwROUNDALLOC==%d sizeof(mwData)==%d mwDataSize==%d\n",
477 mwROUNDALLOC, sizeof(mwData), mwDataSize );
478/**************************************************************** Generic */
479
480/************************************************************ Microsoft C */
481#ifdef _MSC_VER
482 mwWrite( "Compiled using Microsoft C" CPPTEXT
483 " %d.%02d\n", _MSC_VER / 100, _MSC_VER % 100 );
484#endif /* _MSC_VER */
485/************************************************************ Microsoft C */
486
487/************************************************************** Borland C */
488#ifdef __BORLANDC__
489 mwWrite( "Compiled using Borland C"
490#ifdef __cplusplus
491 "++ %d.%01d\n", __BCPLUSPLUS__/0x100, (__BCPLUSPLUS__%0x100)/0x10 );
492#else
493 " %d.%01d\n", __BORLANDC__/0x100, (__BORLANDC__%0x100)/0x10 );
494#endif /* __cplusplus */
495#endif /* __BORLANDC__ */
496/************************************************************** Borland C */
497
498/************************************************************** Watcom C */
499#ifdef __WATCOMC__
500 mwWrite( "Compiled using Watcom C %d.%02d ",
501 __WATCOMC__/100, __WATCOMC__%100 );
502#ifdef __FLAT__
503 mwWrite( "(32-bit flat model)" );
504#endif /* __FLAT__ */
505 mwWrite( "\n" );
506#endif /* __WATCOMC__ */
507/************************************************************** Watcom C */
508
509 mwWrite( "\n" );
510 FLUSH();
511 }
512
513 if( mwUseAtexit ) (void) atexit( mwAbort );
514 return;
515 }
#define VERSION
#define MW_MUTEX_INIT()
void mwAbort(void)
#define CPPTEXT

◆ mwIsReadAddr()

int mwIsReadAddr ( const void * p,
unsigned len )

Definition at line 2491 of file KalFitMemLeak.c.

2492{
2493 if( p == NULL ) return 0;
2494 if( len == 0 ) return 1;
2495 return 1;
2496}

Referenced by mwMark().

◆ mwIsSafeAddr()

int mwIsSafeAddr ( void * p,
unsigned len )

Definition at line 2497 of file KalFitMemLeak.c.

2498{
2499 if( p == NULL ) return 0;
2500 if( len == 0 ) return 1;
2501 return 1;
2502}

◆ mwLimit()

void mwLimit ( long lim)

Definition at line 1202 of file KalFitMemLeak.c.

1202 {
1203 TESTS(NULL,0);
1204 mwWrite("limit: old limit = ");
1205 if( !mwAllocLimit ) mwWrite( "none" );
1206 else mwWrite( "%ld bytes", mwAllocLimit );
1207 mwWrite( ", new limit = ");
1208 if( !lim ) {
1209 mwWrite( "none\n" );
1210 mwUseLimit = 0;
1211 }
1212 else {
1213 mwWrite( "%ld bytes\n", lim );
1214 mwUseLimit = 1;
1215 }
1216 mwAllocLimit = lim;
1217 FLUSH();
1218 }

◆ mwMalloc()

void * mwMalloc ( size_t size,
const char * file,
int line )

Definition at line 863 of file KalFitMemLeak.c.

863 {
864 size_t needed;
865 mwData *mw;
866 char *ptr;
867 void *p;
868
869 mwAutoInit();
870
872
873 TESTS(file,line);
874
875 mwCounter ++;
876 needed = mwDataSize + mwOverflowZoneSize*2 + size;
877 if( needed < size )
878 {
879 /* theoretical case: req size + mw overhead exceeded size_t limits */
880 return NULL;
881 }
882
883 /* if this allocation would violate the limit, fail it */
884 if( mwUseLimit && ((long)size + mwStatCurAlloc > mwAllocLimit) ) {
885 mwWrite( "limit fail: <%ld> %s(%d), %ld wanted %ld available\n",
886 mwCounter, file, line, (long)size, mwAllocLimit - mwStatCurAlloc );
887 mwIncErr();
888 FLUSH();
890 return NULL;
891 }
892
893 mw = (mwData*) malloc( needed );
894 if( mw == NULL ) {
895 if( mwFreeUp(needed,0) >= needed ) {
896 mw = (mwData*) malloc(needed);
897 if( mw == NULL ) {
898 mwWrite( "internal: mwFreeUp(%u) reported success, but malloc() fails\n", needed );
899 mwIncErr();
900 FLUSH();
901 }
902 }
903 if( mw == NULL ) {
904 mwWrite( "fail: <%ld> %s(%d), %ld wanted %ld allocated\n",
905 mwCounter, file, line, (long)size, mwStatCurAlloc );
906 mwIncErr();
907 FLUSH();
909 return NULL;
910 }
911 }
912
913 mw->count = mwCounter;
914 mw->prev = NULL;
915 mw->next = mwHead;
916 mw->file = file;
917 mw->size = size;
918 mw->line = line;
919 mw->flag = 0;
920 mw->check = CHKVAL(mw);
921
922 if( mwHead ) mwHead->prev = mw;
923 mwHead = mw;
924 if( mwTail == NULL ) mwTail = mw;
925
926 ptr = ((char*)mw) + mwDataSize;
927 mwWriteOF( ptr ); /* '*(long*)ptr = PRECHK;' */
928 ptr += mwOverflowZoneSize;
929 p = ptr;
930 memset( ptr, MW_VAL_NEW, size );
931 ptr += size;
932 mwWriteOF( ptr ); /* '*(long*)ptr = POSTCHK;' */
933
934 mwNumCurAlloc ++;
935 mwStatCurAlloc += (long) size;
936 mwStatTotAlloc += (long) size;
937 if( mwStatCurAlloc > mwStatMaxAlloc )
938 mwStatMaxAlloc = mwStatCurAlloc;
939 mwStatNumAlloc ++;
940
941 if( mwStatLevel ) mwStatAlloc( size, file, line );
942
944 return p;
945 }
#define CHKVAL(mw)
#define MW_VAL_NEW
mwData * prev
mwData * next

◆ mwMalloc_()

void * mwMalloc_ ( size_t size)

Definition at line 1170 of file KalFitMemLeak.c.

1170 {
1171 MW_MUTEX_LOCK();
1172 TESTS(NULL,0);
1174 return malloc( size );
1175 }

◆ mwMark()

void * mwMark ( void * p,
const char * desc,
const char * file,
unsigned line )

Definition at line 718 of file KalFitMemLeak.c.

718 {
719 mwMarker *mrk;
720 unsigned n, isnew;
721 char *buf;
722 int tot, oflow = 0;
723 char wherebuf[128];
724
725 mwAutoInit();
726 TESTS(NULL,0);
727
728 if( desc == NULL ) desc = "unknown";
729 if( file == NULL ) file = "unknown";
730
731 tot = sprintf( wherebuf, "%.48s called from %s(%d)", desc, file, line );
732 if( tot >= (int)sizeof(wherebuf) ) { wherebuf[sizeof(wherebuf)-1] = 0; oflow = 1; }
733
734 if( p == NULL ) {
735 mwWrite("mark: %s(%d), no mark for NULL:'%s' may be set\n", file, line, desc );
736 return p;
737 }
738
739 if( mwFirstMark != NULL && !mwIsReadAddr( mwFirstMark, sizeof( mwMarker ) ) )
740 {
741 mwWrite("mark: %s(%d), mwFirstMark (%p) is trashed, can't mark for %s\n",
742 file, line, mwFirstMark, desc );
743 return p;
744 }
745
746 for( mrk=mwFirstMark; mrk; mrk=mrk->next )
747 {
748 if( mrk->next != NULL && !mwIsReadAddr( mrk->next, sizeof( mwMarker ) ) )
749 {
750 mwWrite("mark: %s(%d), mark(%p)->next(%p) is trashed, can't mark for %s\n",
751 file, line, mrk, mrk->next, desc );
752 return p;
753 }
754 if( mrk->host == p ) break;
755 }
756
757 if( mrk == NULL ) {
758 isnew = 1;
759 mrk = (mwMarker*) malloc( sizeof( mwMarker ) );
760 if( mrk == NULL ) {
761 mwWrite("mark: %s(%d), no mark for %p:'%s', out of memory\n", file, line, p, desc );
762 return p;
763 }
764 mrk->next = NULL;
765 n = 0;
766 }
767 else {
768 isnew = 0;
769 n = strlen( mrk->text );
770 }
771
772 n += strlen( wherebuf );
773 buf = (char*) malloc( n+3 );
774 if( buf == NULL ) {
775 if( isnew ) free( mrk );
776 mwWrite("mark: %s(%d), no mark for %p:'%s', out of memory\n", file, line, p, desc );
777 return p;
778 }
779
780 if( isnew ) {
781 memcpy( buf, wherebuf, n+1 );
782 mrk->next = mwFirstMark;
783 mrk->host = p;
784 mrk->text = buf;
785 mrk->level = 1;
786 mwFirstMark = mrk;
787 }
788 else {
789 strcpy( buf, mrk->text );
790 strcat( buf, ", " );
791 strcat( buf, wherebuf );
792 free( mrk->text );
793 mrk->text = buf;
794 mrk->level ++;
795 }
796
797 if( oflow ) {
798 mwIncErr();
799 mwTrace( " [WARNING: OUTPUT BUFFER OVERFLOW - SYSTEM UNSTABLE]\n" );
800 }
801 return p;
802 }
const Int_t n
int mwIsReadAddr(const void *p, unsigned len)
#define mwTrace

◆ mwNoMansLand()

void mwNoMansLand ( int level)

Definition at line 1489 of file KalFitMemLeak.c.

1489 {
1490 mwAutoInit();
1491 TESTS(NULL,0);
1492 switch( level ) {
1493 case MW_NML_NONE:
1494 (void) mwDrop_( 0, MW_VAL_NML, 0 );
1495 break;
1496 case MW_NML_FREE:
1497 break;
1498 case MW_NML_ALL:
1499 (void) mwGrab_( 0, MW_VAL_NML, 0 );
1500 break;
1501 default:
1502 return;
1503 }
1504 mwNML = level;
1505 }
#define MW_NML_NONE
#define MW_NML_ALL
#define MW_NML_FREE

◆ mwRealloc()

void * mwRealloc ( void * p,
size_t size,
const char * file,
int line )

Definition at line 947 of file KalFitMemLeak.c.

947 {
948 int oldUseLimit, i;
949 mwData *mw;
950 char *ptr;
951
952 mwAutoInit();
953
954 if( p == NULL ) return mwMalloc( size, file, line );
955 if( size == 0 ) { mwFree( p, file, line ); return NULL; }
956
958
959 /* do the quick ownership test */
960 mw = (mwData*) mwBUFFER_TO_MW( p );
961 if( mwIsOwned( mw, file, line ) ) {
962
963 /* if the buffer is an NML, treat this as a double-free */
964 if( mw->flag & MW_NML )
965 {
966 mwIncErr();
967 if( *((unsigned char*)(mw)+mwDataSize+mwOverflowZoneSize) != MW_VAL_NML )
968 {
969 mwWrite( "internal: <%ld> %s(%d), no-mans-land MW-%p is corrupted\n",
970 mwCounter, file, line, mw );
971 }
972 goto check_dbl_free;
973 }
974
975 /* if this allocation would violate the limit, fail it */
976 if( mwUseLimit && ((long)size + mwStatCurAlloc - (long)mw->size > mwAllocLimit) ) {
977 TESTS(file,line);
978 mwCounter ++;
979 mwWrite( "limit fail: <%ld> %s(%d), %ld wanted %ld available\n",
980 mwCounter, file, line, (unsigned long)size - mw->size, mwAllocLimit - mwStatCurAlloc );
981 mwIncErr();
982 FLUSH();
984 return NULL;
985 }
986
987 /* fake realloc operation */
988 oldUseLimit = mwUseLimit;
989 mwUseLimit = 0;
990 ptr = (char*) mwMalloc( size, file, line );
991 if( ptr != NULL ) {
992 if( size < mw->size )
993 memcpy( ptr, p, size );
994 else
995 memcpy( ptr, p, mw->size );
996 mwFree( p, file, line );
997 }
998 mwUseLimit = oldUseLimit;
1000 return (void*) ptr;
1001 }
1002
1003 /* Unknown pointer! */
1004
1005 /* using free'd pointer? */
1006check_dbl_free:
1007 for(i=0;i<MW_FREE_LIST;i++) {
1008 if( mwLastFree[i] == p ) {
1009 mwIncErr();
1010 mwWrite( "realloc: <%ld> %s(%d), %p was"
1011 " freed from %s(%d)\n",
1012 mwCounter, file, line, p,
1013 mwLFfile[i], mwLFline[i] );
1014 FLUSH();
1016 return NULL;
1017 }
1018 }
1019
1020 /* some weird pointer */
1021 mwIncErr();
1022 mwWrite( "realloc: <%ld> %s(%d), unknown pointer %p\n",
1023 mwCounter, file, line, p );
1024 FLUSH();
1026 return NULL;
1027 }
#define mwFree(p)

◆ mwRealloc_()

void * mwRealloc_ ( void * p,
size_t size )

Definition at line 1177 of file KalFitMemLeak.c.

1177 {
1178 MW_MUTEX_LOCK();
1179 TESTS(NULL,0);
1181 return realloc( p, size );
1182 }

◆ mwSetAriAction()

void mwSetAriAction ( int action)

Definition at line 1220 of file KalFitMemLeak.c.

1220 {
1221 MW_MUTEX_LOCK();
1222 TESTS(NULL,0);
1223 mwAriAction = action;
1225 return;
1226 }

◆ mwSetAriFunc()

void mwSetAriFunc ( int(* func )(const char *))

Definition at line 854 of file KalFitMemLeak.c.

854 {
855 mwAutoInit();
856 mwAriFunction = func;
857 }

◆ mwSetOutFunc()

void mwSetOutFunc ( void(* func )(int))

Definition at line 655 of file KalFitMemLeak.c.

655 {
656 mwAutoInit();
657 mwOutFunction = func;
658 }

◆ mwStatistics()

void mwStatistics ( int level)

Definition at line 637 of file KalFitMemLeak.c.

638{
639 mwAutoInit();
640 if( level<0 ) level=0;
641 if( mwStatLevel != level )
642 {
643 mwWrite( "statistics: now collecting on a %s basis\n",
644 level<1?"global":(level<2?"module":"line") );
645 mwStatLevel = level;
646 }
647}

◆ mwStrdup()

char * mwStrdup ( const char * str,
const char * file,
int line )

Definition at line 1029 of file KalFitMemLeak.c.

1029 {
1030 size_t len;
1031 char *newstring;
1032
1033 MW_MUTEX_LOCK();
1034
1035 if( str == NULL ) {
1036 mwIncErr();
1037 mwWrite( "strdup: <%ld> %s(%d), strdup(NULL) called\n",
1038 mwCounter, file, line );
1039 FLUSH();
1041 return NULL;
1042 }
1043
1044 len = strlen( str ) + 1;
1045 newstring = (char*) mwMalloc( len, file, line );
1046 if( newstring != NULL ) memcpy( newstring, str, len );
1048 return newstring;
1049 }

◆ mwTerm()

void mwTerm ( void )

Definition at line 625 of file KalFitMemLeak.c.

625 {
626 if( mwInited == 1 )
627 {
628 mwAbort();
629 return;
630 }
631 if( !mwInited )
632 mwWrite("internal: mwTerm(): MEMWATCH has not been started!\n");
633 else
634 mwInited --;
635 }

◆ mwTest()

int mwTest ( const char * file,
int line,
int items )

Definition at line 685 of file KalFitMemLeak.c.

685 {
686 mwAutoInit();
687 mwTestFlags = items;
688 return mwTestNow( file, line, 0 );
689 }

◆ mwTestBuffer()

int mwTestBuffer ( const char * file,
int line,
void * p )

Definition at line 695 of file KalFitMemLeak.c.

695 {
696 mwData* mw;
697
698 mwAutoInit();
699
700 /* do the quick ownership test */
701 mw = (mwData*) mwBUFFER_TO_MW( p );
702
703 if( mwIsOwned( mw, file, line ) ) {
704 return mwTestBuf( mw, file, line );
705 }
706 return 1;
707 }

◆ mwTrace()

void mwTrace ( const char * format,
... )

Definition at line 1343 of file KalFitMemLeak.c.

1343 {
1344 int tot, oflow = 0;
1345 va_list mark;
1346
1347 mwAutoInit();
1348 MW_MUTEX_LOCK();
1349 TESTS(NULL,0);
1350 if( mwOutFunction == NULL ) mwOutFunction = mwDefaultOutFunc;
1351
1352 va_start( mark, format );
1353 tot = vsprintf( mwPrintBuf, format, mark );
1354 va_end( mark );
1355 if( tot >= MW_TRACE_BUFFER ) { mwPrintBuf[MW_TRACE_BUFFER] = 0; oflow = 1; }
1356 for(tot=0;mwPrintBuf[tot];tot++)
1357 (*mwOutFunction)( mwPrintBuf[tot] );
1358 if( oflow ) {
1359 mwIncErr();
1360 mwTrace( " [WARNING: OUTPUT BUFFER OVERFLOW - SYSTEM UNSTABLE]\n" );
1361 }
1362
1363 FLUSH();
1365 }

◆ mwUnmark()

void * mwUnmark ( void * p,
const char * file,
unsigned line )

Definition at line 804 of file KalFitMemLeak.c.

804 {
805 mwMarker *mrk, *prv;
806 mrk = mwFirstMark;
807 prv = NULL;
808 while( mrk ) {
809 if( mrk->host == p ) {
810 if( mrk->level < 2 ) {
811 if( prv ) prv->next = mrk->next;
812 else mwFirstMark = mrk->next;
813 free( mrk->text );
814 free( mrk );
815 return p;
816 }
817 mrk->level --;
818 return p;
819 }
820 prv = mrk;
821 mrk = mrk->next;
822 }
823 mwWrite("mark: %s(%d), no mark found for %p\n", file, line, p );
824 return p;
825 }

◆ mwVerify()

int mwVerify ( int exp,
const char * exps,
const char * fn,
int ln )

Definition at line 1287 of file KalFitMemLeak.c.

1287 {
1288 int i;
1289 char buffer[MW_TRACE_BUFFER+8];
1290 if( exp ) {
1291 return 0;
1292 }
1293 mwAutoInit();
1294 MW_MUTEX_LOCK();
1295 TESTS(fn,ln);
1296 mwIncErr();
1297 mwCounter++;
1298 mwWrite( "verify trap: <%ld> %s(%d), %s\n", mwCounter, fn, ln, exps );
1299 if( mwAriFunction != NULL ) {
1300 sprintf( buffer, "MEMWATCH: verify trap: %s(%d), %s", fn, ln, exps );
1301 i = (*mwAriFunction)(buffer);
1302 if( i == 0 ) {
1303 mwWrite( "verify trap: <%ld> IGNORED - execution continues\n", mwCounter );
1305 return 0;
1306 }
1307 if( i == 1 ) {
1308 mwWrite( "verify trap: <%ld> RETRY - executing again\n", mwCounter );
1310 return 1;
1311 }
1312 }
1313 else {
1314 if( mwAriAction & MW_ARI_NULLREAD ) {
1315 /* This is made in an attempt to kick in */
1316 /* any debuggers or OS stack traces */
1317 FLUSH();
1318 /*lint -save -e413 */
1319 i = *((int*)NULL);
1320 mwDummy( (char)i );
1321 /*lint -restore */
1322 }
1323 if( mwAriAction & MW_ARI_IGNORE ) {
1324 mwWrite( "verify trap: <%ld> AUTO IGNORED - execution continues\n", mwCounter );
1326 return 0;
1327 }
1328 fprintf(mwSTDERR,"\nMEMWATCH: verify trap: %s(%d), %s\n", fn, ln, exps );
1329 }
1330 FLUSH();
1331 (void) mwTestNow( fn, ln, 1 );
1332 FLUSH();
1334 exit(255);
1335 /* NOT REACHED - the return statement is in to keep */
1336 /* stupid compilers from squeaking about differing return modes. */
1337 /* Smart compilers instead say 'code unreachable...' */
1338 /*lint -save -e527 */
1339 return 0;
1340 /*lint -restore */
1341 }