101# define MEMWATCH_NOCPP
104# define MEMWATCH_STDIO
125#if defined( WIN32 ) || defined( __WIN32__ )
126# define MW_HAVE_MUTEX 1
130#if defined( MW_PTHREADS ) || defined( HAVE_PTHREAD_H )
131# define MW_HAVE_MUTEX 1
140#define VERSION "2.71"
141#define CHKVAL( mw ) ( 0xFE0180L ^ (long)mw->count ^ (long)mw->size ^ (long)mw->line )
142#define FLUSH() mwFlush()
143#define TESTS( f, l ) \
144 if ( mwTestAlways ) (void)mwTestNow( f, l, 1 )
145#define PRECHK 0x01234567L
146#define POSTCHK 0x76543210L
147#define mwBUFFER_TO_MW( p ) \
148 ( (mwData*)(void*)( ( (char*)p ) - mwDataSize - mwOverflowZoneSize ) )
166# define mwSTDERR stderr
168# define mwSTDERR mwLog
172# define MW_MUTEX_INIT() mwMutexInit()
173# define MW_MUTEX_TERM() mwMutexTerm()
174# define MW_MUTEX_LOCK() mwMutexLock()
175# define MW_MUTEX_UNLOCK() mwMutexUnlock()
177# define MW_MUTEX_INIT()
178# define MW_MUTEX_TERM()
179# define MW_MUTEX_LOCK()
180# define MW_MUTEX_UNLOCK()
188#ifndef mwBYTE_DEFINED
190# error need CHAR_BIT to be 8!
192typedef unsigned char mwBYTE;
193# define mwBYTE_DEFINED 1
197#if defined( ULONGLONG_MAX ) || defined( ULLONG_MAX ) || defined( _UI64_MAX ) || \
198 defined( ULONG_LONG_MAX )
200# define mwROUNDALLOC_DEFAULT 8
202# if UINT_MAX <= 0xFFFFUL
204# define mwROUNDALLOC_DEFAULT 2
206# if ULONG_MAX > 0xFFFFFFFFUL
208# define mwROUNDALLOC_DEFAULT 8
211# define mwROUNDALLOC_DEFAULT 4
221# define mwROUNDALLOC mwROUNDALLOC_DEFAULT
224#ifndef mwDWORD_DEFINED
225# if ULONG_MAX == 0xFFFFFFFFUL
226typedef unsigned long mwDWORD;
227# define mwDWORD_DEFINED "unsigned long"
231#ifndef mwDWORD_DEFINED
232# if UINT_MAX == 0xFFFFFFFFUL
233typedef unsigned int mwDWORD;
234# define mwDWORD_DEFINED "unsigned int"
238#ifndef mwDWORD_DEFINED
239# if USHRT_MAX == 0xFFFFFFFFUL
240typedef unsigned short mwDWORD;
241# define mwDWORD_DEFINED "unsigned short"
245#ifndef mwBYTE_DEFINED
246# error "can't find out the correct type for a 8 bit scalar"
249#ifndef mwDWORD_DEFINED
250# error "can't find out the correct type for a 32 bit scalar"
301#if defined( WIN32 ) || defined( __WIN32__ )
302typedef HANDLE mwMutex;
305#if defined( MW_PTHREADS ) || defined( HAVE_PTHREAD_H )
306typedef pthread_mutex_t mwMutex;
313static int mwInited = 0;
314static int mwInfoWritten = 0;
315static int mwUseAtexit = 0;
316static FILE* mwLog = NULL;
317static int mwFlushing = 0;
321static long mwAllocLimit = 0L;
322static int mwUseLimit = 0;
324static long mwNumCurAlloc = 0L;
325static mwData* mwHead = NULL;
326static mwData* mwTail = NULL;
327static int mwDataSize = 0;
328static unsigned char mwOverflowZoneTemplate[] =
"mEmwAtch";
331static void ( *mwOutFunction )( int ) = NULL;
332static int ( *mwAriFunction )(
const char* ) = NULL;
338static long mwErrors = 0L;
340static int mwTestFlags = 0;
341static int mwTestAlways = 0;
343static FILE* mwLogB1 = NULL;
344static int mwFlushingB1 = 0;
346static mwStat* mwStatList = NULL;
347static long mwStatTotAlloc = 0L;
348static long mwStatMaxAlloc = 0L;
349static long mwStatNumAlloc = 0L;
350static long mwStatCurAlloc = 0L;
351static long mwNmlNumAlloc = 0L;
352static long mwNmlCurAlloc = 0L;
355static long mwGrabSize = 0L;
360static int mwLFcur = 0;
364static FILE* mwLogB2 = NULL;
365static int mwFlushingB2 = 0;
368static mwMutex mwGlobalMutex;
375static void mwAutoInit(
void );
376static FILE* mwLogR(
void );
377static void mwLogW( FILE* );
378static int mwFlushR(
void );
379static void mwFlushW(
int );
380static void mwFlush(
void );
381static void mwIncErr(
void );
382static void mwUnlink(
mwData*,
const char*
file,
int line );
383static int mwRelink(
mwData*,
const char*
file,
int line );
384static int mwIsHeapOK(
mwData* mw );
385static int mwIsOwned(
mwData* mw,
const char*
file,
int line );
386static int mwTestBuf(
mwData* mw,
const char*
file,
int line );
387static void mwDefaultOutFunc(
int );
388static void mwWrite(
const char* format, ... );
389static void mwLogFile(
const char* name );
390static size_t mwFreeUp(
size_t,
int );
391static const void* mwTestMem(
const void*,
unsigned,
int );
392static int mwStrCmpI(
const char* s1,
const char* s2 );
393static int mwTestNow(
const char*
file,
int line,
int always_invoked );
394static void mwDropAll(
void );
395static const char* mwGrabType(
int type );
396static unsigned mwGrab_(
unsigned kb,
int type,
int silent );
397static unsigned mwDrop_(
unsigned kb,
int type,
int silent );
398static int mwARI(
const char*
text );
399static void mwStatReport(
void );
400static mwStat* mwStatGet(
const char*,
int,
int );
401static void mwStatAlloc(
size_t,
const char*,
int );
402static void mwStatFree(
size_t,
const char*,
int );
403static int mwCheckOF(
const void* p );
404static void mwWriteOF(
void* p );
405static char mwDummy(
char c );
407static void mwMutexInit(
void );
408static void mwMutexTerm(
void );
409static void mwMutexLock(
void );
410static void mwMutexUnlock(
void );
420 if ( mwInited++ > 0 )
return;
425 if ( mwLogR() == NULL ) mwLogFile(
"memwatch.log" );
426 if ( mwLogR() == NULL )
433 for ( i = 1; i < 100; i++ )
435 sprintf( buf,
"memwat%02d.log", i );
437 if ( mwLogR() != NULL )
break;
451 mwDataSize =
sizeof(
mwData );
455 if ( !mwInfoWritten )
459 mwWrite(
"\n============="
460 " MEMWATCH " VERSION " Copyright (C) 1992-1999 Johan Lindh "
462 mwWrite(
"\nStarted at %s\n", ctime( &tid ) );
465 mwWrite(
"Modes: " );
470 mwWrite(
"__STDC__ " );
473 mwWrite(
"16-bit " );
476 mwWrite(
"32-bit " );
479 mwWrite(
"64-bit " );
481 mwWrite(
"mwDWORD==(" mwDWORD_DEFINED
")\n" );
482 mwWrite(
"mwROUNDALLOC==%d sizeof(mwData)==%d mwDataSize==%d\n",
mwROUNDALLOC,
483 sizeof(
mwData ), mwDataSize );
488 mwWrite(
"Compiled using Microsoft C" CPPTEXT " %d.%02d\n", _MSC_VER / 100,
495 mwWrite(
"Compiled using Borland C"
498 __BCPLUSPLUS__ / 0x100, ( __BCPLUSPLUS__ % 0x100 ) / 0x10 );
501 __BORLANDC__ / 0x100, ( __BORLANDC__ % 0x100 ) / 0x10 );
508 mwWrite(
"Compiled using Watcom C %d.%02d ", __WATCOMC__ / 100, __WATCOMC__ % 100 );
510 mwWrite(
"(32-bit flat model)" );
520 if ( mwUseAtexit ) (void)atexit(
mwAbort );
533 mwWrite(
"\nStopped at %s\n", ctime( &tid ) );
535 if ( !mwInited ) mwWrite(
"internal: mwAbort(): MEMWATCH not initialized!\n" );
541 while ( mwFirstMark )
543 mrk = mwFirstMark->
next;
544 mwWrite(
"mark: %p: %s\n", mwFirstMark->host, mwFirstMark->text );
545 free( mwFirstMark->text );
553 while ( mwHead != NULL && errors < 3 )
555 if ( !mwIsOwned( mwHead, __FILE__, __LINE__ ) )
560 mwWrite(
"internal: NML/unfreed scan restarting\n" );
565 mwWrite(
"internal: NML/unfreed scan aborted, heap too damaged\n" );
570 if ( !( mwHead->flag &
MW_NML ) )
573 data = ( (
char*)mwHead ) + mwDataSize;
574 mwWrite(
"unfreed: <%ld> %s(%d), %ld bytes at %p ", mwHead->count, mwHead->file,
575 mwHead->line, (
long)mwHead->size,
data + mwOverflowZoneSize );
576 if ( mwCheckOF(
data ) )
578 mwWrite(
"[underflowed] " );
581 if ( mwCheckOF( (
data + mwOverflowZoneSize + mwHead->size ) ) )
583 mwWrite(
"[overflowed] " );
588 if ( mwHead->size < 16 ) j = (int)mwHead->size;
589 for ( i = 0; i < 16; i++ )
591 if ( i < j ) mwWrite(
"%02X ", (
unsigned char)*(
data + mwOverflowZoneSize + i ) );
592 else mwWrite(
".. " );
594 for ( i = 0; i < j; i++ )
596 c = *(
data + mwOverflowZoneSize + i );
597 if ( c < 32 || c > 126 ) c =
'.';
602 mwUnlink( mw, __FILE__, __LINE__ );
607 data = ( (
char*)mwHead ) + mwDataSize + mwOverflowZoneSize;
611 mwWrite(
"wild pointer: <%ld> NoMansLand %p alloc'd at %s(%d)\n", mwHead->count,
612 data + mwOverflowZoneSize, mwHead->file, mwHead->line );
616 mwNmlCurAlloc -= mwHead->size;
618 mwUnlink( mw, __FILE__, __LINE__ );
624 mwWrite(
"internal: NoMansLand block counter %ld, not zero\n", mwNmlNumAlloc );
626 mwWrite(
"internal: NoMansLand byte counter %ld, not zero\n", mwNmlCurAlloc );
633 mwHead = mwTail = NULL;
634 if ( mwErrors ) fprintf(
mwSTDERR,
"MEMWATCH detected %ld anomalies\n", mwErrors );
647 if ( !mwInited ) mwWrite(
"internal: mwTerm(): MEMWATCH has not been started!\n" );
653 if ( level < 0 ) level = 0;
654 if ( mwStatLevel != level )
656 mwWrite(
"statistics: now collecting on a %s basis\n",
657 level < 1 ?
"global" : ( level < 2 ?
"module" :
"line" ) );
664 mwTestAlways = onoff;
670 mwOutFunction = func;
673static void mwWriteOF(
void* p ) {
676 ptr = (
unsigned char*)p;
677 for ( i = 0; i < mwOverflowZoneSize; i++ ) { *( ptr + i ) = mwOverflowZoneTemplate[i % 8]; }
681static int mwCheckOF(
const void* p ) {
683 const unsigned char* ptr;
684 ptr = (
const unsigned char*)p;
685 for ( i = 0; i < mwOverflowZoneSize; i++ )
687 if ( *( ptr + i ) != mwOverflowZoneTemplate[i % 8] )
return 1;
695 return mwTestNow(
file, line, 0 );
710 if ( mwIsOwned( mw,
file, line ) ) {
return mwTestBuf( mw,
file, line ); }
715 fprintf(
mwSTDERR,
"breakout: %s\n", cause );
716 mwWrite(
"breakout: %s\n", cause );
723void*
mwMark(
void* p,
const char* desc,
const char*
file,
unsigned line ) {
733 if ( desc == NULL ) desc =
"unknown";
734 if (
file == NULL )
file =
"unknown";
736 tot =
sprintf( wherebuf,
"%.48s called from %s(%d)", desc,
file, line );
737 if ( tot >= (
int)
sizeof( wherebuf ) )
739 wherebuf[
sizeof( wherebuf ) - 1] = 0;
745 mwWrite(
"mark: %s(%d), no mark for NULL:'%s' may be set\n",
file, line, desc );
751 mwWrite(
"mark: %s(%d), mwFirstMark (%p) is trashed, can't mark for %s\n",
file, line,
756 for ( mrk = mwFirstMark; mrk; mrk = mrk->
next )
760 mwWrite(
"mark: %s(%d), mark(%p)->next(%p) is trashed, can't mark for %s\n",
file, line,
761 mrk, mrk->
next, desc );
764 if ( mrk->
host == p )
break;
773 mwWrite(
"mark: %s(%d), no mark for %p:'%s', out of memory\n",
file, line, p, desc );
782 n = strlen( mrk->
text );
785 n += strlen( wherebuf );
786 buf = (
char*)malloc(
n + 3 );
789 if ( isnew ) free( mrk );
790 mwWrite(
"mark: %s(%d), no mark for %p:'%s', out of memory\n",
file, line, p, desc );
796 memcpy( buf, wherebuf,
n + 1 );
797 mrk->
next = mwFirstMark;
805 strcpy( buf, mrk->
text );
807 strcat( buf, wherebuf );
816 mwTrace(
" [WARNING: OUTPUT BUFFER OVERFLOW - SYSTEM UNSTABLE]\n" );
827 if ( mrk->
host == p )
829 if ( mrk->
level < 2 )
832 else mwFirstMark = mrk->
next;
843 mwWrite(
"mark: %s(%d), no mark found for %p\n",
file, line, p );
851static int mwARI(
const char* estr ) {
854 fprintf(
mwSTDERR,
"\n%s\nMEMWATCH: Abort, Retry or Ignore? ", estr );
855 (void)fgets( inbuf,
sizeof( inbuf ), stdin );
856 for ( c = 0; inbuf[c] && inbuf[c] <=
' '; c++ )
859 if ( c ==
'R' || c ==
'r' )
871 return mwARI( estr );
877 mwAriFunction = func;
897 needed = mwDataSize + mwOverflowZoneSize * 2 + size;
905 if ( mwUseLimit && ( (
long)size + mwStatCurAlloc > mwAllocLimit ) )
907 mwWrite(
"limit fail: <%ld> %s(%d), %ld wanted %ld available\n",
mwCounter,
file, line,
908 (
long)size, mwAllocLimit - mwStatCurAlloc );
915 mw = (
mwData*)malloc( needed );
918 if ( mwFreeUp( needed, 0 ) >= needed )
920 mw = (
mwData*)malloc( needed );
923 mwWrite(
"internal: mwFreeUp(%u) reported success, but malloc() fails\n", needed );
930 mwWrite(
"fail: <%ld> %s(%d), %ld wanted %ld allocated\n",
mwCounter,
file, line,
931 (
long)size, mwStatCurAlloc );
948 if ( mwHead ) mwHead->prev = mw;
950 if ( mwTail == NULL ) mwTail = mw;
952 ptr = ( (
char*)mw ) + mwDataSize;
954 ptr += mwOverflowZoneSize;
961 mwStatCurAlloc += (long)size;
962 mwStatTotAlloc += (long)size;
963 if ( mwStatCurAlloc > mwStatMaxAlloc ) mwStatMaxAlloc = mwStatCurAlloc;
966 if ( mwStatLevel ) mwStatAlloc( size,
file, line );
990 if ( mwIsOwned( mw,
file, line ) )
997 if ( *( (
unsigned char*)( mw ) + mwDataSize + mwOverflowZoneSize ) !=
MW_VAL_NML )
999 mwWrite(
"internal: <%ld> %s(%d), no-mans-land MW-%p is corrupted\n",
mwCounter,
file,
1002 goto check_dbl_free;
1006 if ( mwUseLimit && ( (
long)size + mwStatCurAlloc - (
long)mw->
size > mwAllocLimit ) )
1010 mwWrite(
"limit fail: <%ld> %s(%d), %ld wanted %ld available\n",
mwCounter,
file, line,
1011 (
unsigned long)size - mw->
size, mwAllocLimit - mwStatCurAlloc );
1019 oldUseLimit = mwUseLimit;
1024 if ( size < mw->size ) memcpy( ptr, p, size );
1025 else memcpy( ptr, p, mw->
size );
1028 mwUseLimit = oldUseLimit;
1039 if ( mwLastFree[i] == p )
1042 mwWrite(
"realloc: <%ld> %s(%d), %p was"
1043 " freed from %s(%d)\n",
1053 mwWrite(
"realloc: <%ld> %s(%d), unknown pointer %p\n",
mwCounter,
file, line, p );
1068 mwWrite(
"strdup: <%ld> %s(%d), strdup(NULL) called\n",
mwCounter,
file, line );
1074 len = strlen( str ) + 1;
1076 if ( newstring != NULL ) memcpy( newstring, str, len );
1103 mwWrite(
"NULL free: <%ld> %s(%d), NULL pointer free'd\n",
mwCounter,
file, line );
1112 if ( mwIsOwned( mw,
file, line ) )
1114 (void)mwTestBuf( mw,
file, line );
1119 if ( *( ( (
unsigned char*)mw ) + mwDataSize + mwOverflowZoneSize ) !=
MW_VAL_NML )
1121 mwWrite(
"internal: <%ld> %s(%d), no-mans-land MW-%p is corrupted\n",
mwCounter,
file,
1124 goto check_dbl_free;
1129 mwStatCurAlloc -= (long)mw->
size;
1130 if ( mwStatLevel ) mwStatFree( mw->
size, mw->
file, mw->
line );
1137 mwNmlCurAlloc += (long)mw->
size;
1138 memset( ( (
char*)mw ) + mwDataSize + mwOverflowZoneSize,
MW_VAL_NML, mw->size );
1143 mwUnlink( mw,
file, line );
1145 mw->
size + mwDataSize + mwOverflowZoneSize + mwOverflowZoneSize );
1148 memset( mw,
'.', mwDataSize + mwOverflowZoneSize );
1150 strncpy( (
char*)(
void*)mw, buffer, mwDataSize + mwOverflowZoneSize );
1156 mwLFfile[mwLFcur] =
file;
1157 mwLFline[mwLFcur] = line;
1158 mwLastFree[mwLFcur++] = p;
1169 if ( mwLastFree[i] == p )
1172 mwWrite(
"double-free: <%ld> %s(%d), %p was"
1173 " freed from %s(%d)\n",
1183 mwWrite(
"WILD free: <%ld> %s(%d), unknown pointer %p\n",
mwCounter,
file, line, p );
1191 size_t size = a * b;
1193 if ( p == NULL )
return NULL;
1194 memset( p, 0, size );
1209 return malloc( size );
1216 return realloc( p, size );
1223 return calloc( a, b );
1227 if ( mwLogR() ) fflush( mwLogR() );
1232 mwFlushW( onoff < 1 ? 0 : onoff );
1234 if ( mwLogR() ) fflush( mwLogR() );
1240 mwWrite(
"limit: old limit = " );
1241 if ( !mwAllocLimit ) mwWrite(
"none" );
1242 else mwWrite(
"%ld bytes", mwAllocLimit );
1243 mwWrite(
", new limit = " );
1246 mwWrite(
"none\n" );
1251 mwWrite(
"%ld bytes\n", lim );
1261 mwAriAction = action;
1269 if (
exp ) {
return 0; }
1275 mwWrite(
"assert trap: <%ld> %s(%d), %s\n",
mwCounter, fn, ln, exps );
1276 if ( mwAriFunction != NULL )
1278 sprintf( buffer,
"MEMWATCH: assert trap: %s(%d), %s", fn, ln, exps );
1279 i = ( *mwAriFunction )( buffer );
1283 mwWrite(
"assert trap: <%ld> IGNORED - execution continues\n",
mwCounter );
1287 mwWrite(
"assert trap: <%ld> RETRY - executing again\n",
mwCounter );
1296 mwWrite(
"assert trap: <%ld> AUTO IGNORED - execution continues\n",
mwCounter );
1300 fprintf(
mwSTDERR,
"\nMEMWATCH: assert trap: %s(%d), %s\n", fn, ln, exps );
1304 (void)mwTestNow( fn, ln, 1 );
1313 i = *( (
int*)NULL );
1331 if (
exp ) {
return 0; }
1337 mwWrite(
"verify trap: <%ld> %s(%d), %s\n",
mwCounter, fn, ln, exps );
1338 if ( mwAriFunction != NULL )
1340 sprintf( buffer,
"MEMWATCH: verify trap: %s(%d), %s", fn, ln, exps );
1341 i = ( *mwAriFunction )( buffer );
1344 mwWrite(
"verify trap: <%ld> IGNORED - execution continues\n",
mwCounter );
1350 mwWrite(
"verify trap: <%ld> RETRY - executing again\n",
mwCounter );
1363 i = *( (
int*)NULL );
1369 mwWrite(
"verify trap: <%ld> AUTO IGNORED - execution continues\n",
mwCounter );
1373 fprintf(
mwSTDERR,
"\nMEMWATCH: verify trap: %s(%d), %s\n", fn, ln, exps );
1376 (void)mwTestNow( fn, ln, 1 );
1395 if ( mwOutFunction == NULL ) mwOutFunction = mwDefaultOutFunc;
1397 va_start( mark, format );
1398 tot = vsprintf( mwPrintBuf, format, mark );
1405 for ( tot = 0; mwPrintBuf[tot]; tot++ ) ( *mwOutFunction )( mwPrintBuf[tot] );
1409 mwTrace(
" [WARNING: OUTPUT BUFFER OVERFLOW - SYSTEM UNSTABLE]\n" );
1430static void mwDropAll() {
1434 if ( mwGrabList != NULL )
1435 mwWrite(
"internal: the grab list is not empty after mwDropAll()\n" );
1438static const char* mwGrabType(
int type ) {
1447 return "<unknown type>";
1450static unsigned mwGrab_(
unsigned kb,
int type,
int silent ) {
1453 if ( !kb ) i = kb = 65000U;
1458 ( mwStatCurAlloc + mwGrabSize + (
long)
sizeof(
mwGrabData ) > mwAllocLimit ) )
1462 mwWrite(
"grabbed: all allowed memory to %s (%u kb)\n", mwGrabType(
type ), i - kb );
1472 mwWrite(
"grabbed: all available memory to %s (%u kb)\n", mwGrabType(
type ), i - kb );
1478 gd->
next = mwGrabList;
1485 mwWrite(
"grabbed: %u kilobytes of %s memory\n", i, mwGrabType(
type ) );
1491static unsigned mwDrop_(
unsigned kb,
int type,
int silent ) {
1496 if ( mwGrabList == NULL && kb == 0 )
return 0;
1497 if ( !kb ) i = kb = 60000U;
1505 if ( i - kb > 0 && !silent )
1507 mwWrite(
"dropped: all %s memory (%u kb)\n", mwGrabType(
type ), i - kb );
1514 if ( pr ) pr->next = gd->
next;
1517 if ( mwGrabList == gd ) mwGrabList = gd->
next;
1522 mwWrite(
"wild pointer: <%ld> %s memory hit at %p\n",
mwCounter, mwGrabType(
type ),
1537 mwWrite(
"dropped: %u kilobytes of %s memory\n", i, mwGrabType(
type ) );
1564static void mwAutoInit(
void ) {
1565 if ( mwInited )
return;
1571static FILE* mwLogR() {
1572 if ( ( mwLog == mwLogB1 ) && ( mwLog == mwLogB2 ) )
return mwLog;
1573 if ( mwLog == mwLogB1 ) mwLogB2 = mwLog;
1574 if ( mwLog == mwLogB2 ) mwLogB1 = mwLog;
1575 if ( mwLogB1 == mwLogB2 ) mwLog = mwLogB1;
1576 if ( ( mwLog == mwLogB1 ) && ( mwLog == mwLogB2 ) )
1578 mwWrite(
"internal: log file handle damaged and recovered\n" );
1582 fprintf(
mwSTDERR,
"\nMEMWATCH: log file handle destroyed, using mwSTDERR\n" );
1583 mwLog = mwLogB1 = mwLogB2 =
mwSTDERR;
1587static void mwLogW( FILE* p ) { mwLog = mwLogB1 = mwLogB2 = p; }
1589static int mwFlushR() {
1590 if ( ( mwFlushing == mwFlushingB1 ) && ( mwFlushing == mwFlushingB2 ) )
return mwFlushing;
1591 if ( mwFlushing == mwFlushingB1 ) mwFlushingB2 = mwFlushing;
1592 if ( mwFlushing == mwFlushingB2 ) mwFlushingB1 = mwFlushing;
1593 if ( mwFlushingB1 == mwFlushingB2 ) mwFlushing = mwFlushingB1;
1594 if ( ( mwFlushing == mwFlushingB1 ) && ( mwFlushing == mwFlushingB2 ) )
1596 mwWrite(
"internal: flushing flag damaged and recovered\n" );
1600 mwWrite(
"internal: flushing flag destroyed, so set to true\n" );
1601 mwFlushing = mwFlushingB1 = mwFlushingB2 = 1;
1605static void mwFlushW(
int n ) { mwFlushing = mwFlushingB1 = mwFlushingB2 =
n; }
1607static void mwIncErr() {
1609 mwFlushW( mwFlushR() + 1 );
1613static void mwFlush() {
1614 if ( mwLogR() == NULL )
return;
1618 if ( mwFlushR() ) fflush( mwLogR() );
1623static void mwUnlink(
mwData* mw,
const char*
file,
int line ) {
1624 if ( mw->
prev == NULL )
1627 mwWrite(
"internal: <%ld> %s(%d), MW-%p: link1 NULL, but not head\n",
mwCounter,
file,
1634 mwWrite(
"internal: <%ld> %s(%d), MW-%p: link1 failure\n",
mwCounter,
file, line, mw );
1637 if ( mw->
next == NULL )
1640 mwWrite(
"internal: <%ld> %s(%d), MW-%p: link2 NULL, but not tail\n",
mwCounter,
file,
1647 mwWrite(
"internal: <%ld> %s(%d), MW-%p: link2 failure\n",
mwCounter,
file, line, mw );
1657static int mwRelink(
mwData* mw,
const char*
file,
int line ) {
1663 if (
file == NULL )
file =
"unknown";
1667 mwWrite(
"relink: cannot repair MW at NULL\n" );
1674 mwWrite(
"relink: MW-%p is a garbage pointer\n", mw );
1679 mwWrite(
"relink: <%ld> %s(%d) attempting to repair MW-%p...\n",
mwCounter,
file, line, mw );
1688 mwWrite(
"relink: failed for MW-%p; head pointer destroyed\n", mw );
1692 for ( mw1 = mwHead; mw1; mw1 = mw1->
next )
1694 if ( mw1->
next == mw )
1701 mwWrite(
"relink: failed for MW-%p; forward chain fragmented at MW-%p: 'next' is %p\n",
1702 mw, mw1, mw1->
next );
1709 mwWrite(
"relink: MW-%p not found in forward chain search\n", mw );
1716 mwWrite(
"relink: MW-%p is the head (first) allocation\n", mw );
1717 if ( mw->
prev != NULL )
1719 mwWrite(
"relink: MW-%p prev pointer is non-NULL, you have a wild pointer\n", mw );
1729 mwWrite(
"relink: failed for MW-%p; tail pointer destroyed\n", mw );
1733 for ( mw1 = mwTail; mw1; mw1 = mw1->
prev )
1735 if ( mw1->
prev == mw )
1742 mwWrite(
"relink: failed for MW-%p; reverse chain fragmented at MW-%p, 'prev' is %p\n",
1743 mw, mw1, mw1->
prev );
1750 mwWrite(
"relink: MW-%p not found in reverse chain search\n", mw );
1757 mwWrite(
"relink: MW-%p is the tail (last) allocation\n", mw );
1758 if ( mw->
next != NULL )
1760 mwWrite(
"relink: MW-%p next pointer is non-NULL, you have a wild pointer\n", mw );
1767 mwWrite(
"relink: heap appears intact, MW-%p probably garbage pointer\n", mw );
1775 ms = mwStatGet( mw->
file, -1, 0 );
1776 if ( ms == NULL ) mw->
file =
"<relinked>";
1784 if ( mwHead == NULL && mwTail == NULL )
1786 if ( mwStatCurAlloc == 0 )
1787 mwWrite(
"relink: <%ld> %s(%d) heap is empty, nothing to repair\n",
mwCounter,
file,
1789 else mwWrite(
"relink: <%ld> %s(%d) heap damaged beyond repair\n",
mwCounter,
file, line );
1794 mwWrite(
"relink: <%ld> %s(%d) attempting emergency repairs...\n",
mwCounter,
file, line );
1797 if ( mwHead == NULL || mwTail == NULL )
1799 if ( mwHead == NULL ) mwWrite(
"relink: mwHead is NULL, but mwTail is %p\n", mwTail );
1800 else mwWrite(
"relink: mwTail is NULL, but mwHead is %p\n", mwHead );
1804 if ( mwHead != NULL )
1808 mwWrite(
"relink: mwHead (MW-%p) is damaged, skipping forward scan\n", mwHead );
1812 if ( mwHead->prev != NULL )
1814 mwWrite(
"relink: the mwHead pointer's 'prev' member is %p, not NULL\n", mwHead->prev );
1816 for ( mw1 = mwHead; mw1; mw1 = mw1->
next )
1823 mwWrite(
"relink: forward chain's last intact MW is MW-%p, %ld %sbytes at %s(%d)\n",
1829 "relink: forward chain's first damaged MW is MW-%p, %ld %sbytes at %s(%d)\n",
1835 mwWrite(
"relink: the 'next' pointer of this MW points to %p, which is "
1836 "out-of-legal-access\n",
1847 if ( mwTail != NULL )
1851 mwWrite(
"relink: mwTail (%p) is damaged, skipping reverse scan\n", mwTail );
1855 if ( mwTail->next != NULL )
1857 mwWrite(
"relink: the mwTail pointer's 'next' member is %p, not NULL\n", mwTail->next );
1859 for ( mw2 = mwTail; mw2; mw2 = mw2->
prev )
1866 mwWrite(
"relink: reverse chain's last intact MW is MW-%p, %ld %sbytes at %s(%d)\n",
1872 "relink: reverse chain's first damaged MW is MW-%p, %ld %sbytes at %s(%d)\n",
1878 mwWrite(
"relink: the 'prev' pointer of this MW points to %p, which is "
1879 "out-of-legal-access\n",
1889 if ( mwHead == NULL && mwTail == NULL )
1891 mwWrite(
"relink: both head and tail pointers damaged, aborting program\n" );
1896 if ( mwHead == NULL )
1899 mwWrite(
"relink: heap truncated, MW-%p designated as new mwHead\n", mw2 );
1903 if ( mwTail == NULL )
1906 mwWrite(
"relink: heap truncated, MW-%p designated as new mwTail\n", mw1 );
1910 if ( mw1 == NULL && mw2 == NULL && mwHead->prev == NULL && mwTail->next == NULL )
1912 mwWrite(
"relink: verifying heap integrity...\n" );
1916 if ( mw1 && mw2 && mw1 != mw2 )
1920 mwWrite(
"relink: emergency repairs successful, assessing damage...\n" );
1925 mwWrite(
"relink: heap totally destroyed, aborting program\n" );
1934 if ( !mwIsHeapOK( NULL ) )
1936 mwWrite(
"relink: heap verification FAILS - aborting program\n" );
1941 for ( size =
count = 0, mw1 = mwHead; mw1; mw1 = mw1->
next )
1944 size += (long)mw1->
size;
1946 if (
count == mwNumCurAlloc )
1948 mwWrite(
"relink: successful, " );
1949 if ( size == mwStatCurAlloc ) { mwWrite(
"no allocations lost\n" ); }
1954 mwWrite(
"size information lost for MW-%p\n", mw );
1961 mwWrite(
"relink: partial, %ld MW-blocks of %ld bytes lost\n",
1962 mwNmlNumAlloc + mwNumCurAlloc -
count, mwNmlCurAlloc + mwStatCurAlloc - size );
1977static int mwIsHeapOK(
mwData* includes_mw ) {
1981 for ( mw = mwHead; mw; mw = mw->
next )
1983 if ( includes_mw == mw ) found++;
1988 if ( mw == mwHead || mw->
prev->
next != mw )
return 0;
1993 if ( mw == mwTail || mw->
next->
prev != mw )
return 0;
1995 else if ( mw != mwTail )
return 0;
1998 if ( includes_mw != NULL && !found )
return 0;
2003static int mwIsOwned(
mwData* mw,
const char*
file,
int line ) {
2011 if ( mwHead == NULL && mwTail == NULL && mwStatCurAlloc == 0 )
return 0;
2017 if ( mwIsHeapOK( mw ) )
2020 mwWrite(
"internal: <%ld> %s(%d), checksum for MW-%p is incorrect\n",
mwCounter,
file,
2025 ms = mwStatGet( mw->
file, -1, 0 );
2026 if ( ms == NULL ) mw->
file =
"<relinked>";
2028 else mw->
file =
"<unknown>";
2047 if ( mw->
prev->
next == mw ) retv++;
2051 if ( mwHead == mw ) retv++;
2055 if ( mw->
next->
prev == mw ) retv++;
2059 if ( mwTail == mw ) retv++;
2062 if ( retv > 2 )
return 1;
2066 if ( !mwIsHeapOK( mw ) )
2068 if ( mwRelink( mw,
file, line ) )
return 1;
2072 mwWrite(
"internal: <%ld> %s(%d), mwIsOwned fails for MW-%p\n",
mwCounter,
file, line, mw );
2084static int mwTestBuf(
mwData* mw,
const char*
file,
int line ) {
2088 if (
file == NULL )
file =
"unknown";
2090 if ( !
mwIsSafeAddr( mw, mwDataSize + mwOverflowZoneSize ) )
2092 mwWrite(
"internal: <%ld> %s(%d): pointer MW-%p is invalid\n",
mwCounter,
file, line, mw );
2099 mwWrite(
"internal: <%ld> %s(%d), info trashed; relinking\n",
mwCounter,
file, line );
2101 if ( !mwRelink( mw,
file, line ) )
return 2;
2106 mwWrite(
"internal: <%ld> %s(%d), buffer <%ld> %s(%d) link1 broken\n",
mwCounter,
file,
2109 if ( !mwRelink( mw,
file, line ) ) retv = 2;
2113 mwWrite(
"internal: <%ld> %s(%d), buffer <%ld> %s(%d) link2 broken\n",
mwCounter,
file,
2116 if ( !mwRelink( mw,
file, line ) ) retv = 2;
2119 p = ( (
char*)mw ) + mwDataSize;
2120 if ( mwCheckOF( p ) )
2122 mwWrite(
"underflow: <%ld> %s(%d), %ld bytes alloc'd at <%ld> %s(%d)\n",
mwCounter,
file,
2127 p += mwOverflowZoneSize + mw->
size;
2128 if (
mwIsReadAddr( p, mwOverflowZoneSize ) && mwCheckOF( p ) )
2130 mwWrite(
"overflow: <%ld> %s(%d), %ld bytes alloc'd at <%ld> %s(%d)\n",
mwCounter,
file,
2139static void mwDefaultOutFunc(
int c ) {
2140 if ( mwLogR() ) fputc( c, mwLogR() );
2143static void mwWrite(
const char* format, ... ) {
2147 if ( mwOutFunction == NULL ) mwOutFunction = mwDefaultOutFunc;
2148 va_start( mark, format );
2149 tot = vsprintf( mwPrintBuf, format, mark );
2156 for ( tot = 0; mwPrintBuf[tot]; tot++ ) ( *mwOutFunction )( mwPrintBuf[tot] );
2159 mwWrite(
"\ninternal: mwWrite(): WARNING! OUTPUT EXCEEDED %u CHARS: SYSTEM UNSTABLE\n",
2166static void mwLogFile(
const char* name ) {
2169 if ( mwLogR() != NULL )
2174 if ( name == NULL )
return;
2175 mwLogW( fopen( name,
"a" COMMIT ) );
2176 if ( mwLogR() == NULL ) mwWrite(
"logfile: failed to open/create file '%s'\n", name );
2185static size_t mwFreeUp(
size_t needed,
int urgent ) {
2193 if ( mwDrop_( 1,
MW_VAL_NML, 1 ) == 0 )
break;
2194 p = malloc( needed );
2195 if ( p == NULL )
continue;
2202 while ( mw != NULL )
2207 data = ( (
char*)mw ) + mwDataSize + mwOverflowZoneSize;
2211 mwWrite(
"wild pointer: <%ld> NoMansLand %p alloc'd at %s(%d)\n", mw->
count,
2215 mwUnlink( mw,
"mwFreeUp", 0 );
2218 p = malloc( needed );
2219 if ( p == NULL )
continue;
2226 if ( !urgent )
return 0;
2231 if ( mwDrop_( 1,
MW_VAL_GRB, 1 ) == 0 )
break;
2232 p = malloc( needed );
2233 if ( p == NULL )
continue;
2241static const void* mwTestMem(
const void* p,
unsigned len,
int c ) {
2242 const unsigned char* ptr;
2243 ptr = (
const unsigned char*)p;
2246 if ( *ptr != (
unsigned char)c )
return (
const void*)ptr;
2252static int mwStrCmpI(
const char* s1,
const char* s2 ) {
2253 if ( s1 == NULL || s2 == NULL )
return 0;
2256 if ( toupper( *s2 ) == toupper( *s1 ) )
2268 if ( always_invoked ) \
2270 mwWrite( "autocheck: <%ld> %s(%d) ", mwCounter, file, line ); \
2271 always_invoked = 0; \
2274static int mwTestNow(
const char*
file,
int line,
int always_invoked ) {
2279 if (
file && !always_invoked )
2280 mwWrite(
"check: <%ld> %s(%d), checking %s%s%s\n",
mwCounter,
file, line,
2283 ( mwTestFlags &
MW_TEST_NML ) ?
"nomansland " :
"" );
2287 for ( mw = mwHead; mw; mw = mw->
next )
2292 mwWrite(
"check: heap corruption detected\n" );
2301 mwWrite(
"check: heap corruption detected\n" );
2305 if ( mw == mwHead || mw->
prev->
next != mw )
2308 mwWrite(
"check: heap chain broken, prev link incorrect\n" );
2318 mwWrite(
"check: heap corruption detected\n" );
2322 if ( mw == mwTail || mw->
next->
prev != mw )
2325 mwWrite(
"check: heap chain broken, next link incorrect\n" );
2330 else if ( mw != mwTail )
2333 mwWrite(
"check: heap chain broken, tail incorrect\n" );
2341 for ( mw = mwHead; mw; mw = mw->
next )
2343 if ( mwTestBuf( mw,
file, line ) ) retv++;
2348 for ( mw = mwHead; mw; mw = mw->
next )
2352 data = ( (
char*)mw ) + mwDataSize + mwOverflowZoneSize;
2356 mwWrite(
"wild pointer: <%ld> NoMansLand %p alloc'd at %s(%d)\n", mw->
count,
2363 if (
file && !always_invoked && !retv )
2364 mwWrite(
"check: <%ld> %s(%d), complete; no errors\n",
mwCounter,
file, line );
2372static void mwStatReport() {
2374 const char* modname;
2378 mwWrite(
"\nMemory usage statistics (global):\n" );
2379 mwWrite(
" N)umber of allocations made: %ld\n", mwStatNumAlloc );
2380 mwWrite(
" L)argest memory usage : %ld\n", mwStatMaxAlloc );
2381 mwWrite(
" T)otal of all alloc() calls: %ld\n", mwStatTotAlloc );
2382 mwWrite(
" U)nfreed bytes totals : %ld\n", mwStatCurAlloc );
2385 if ( mwStatLevel < 1 )
return;
2388 mwWrite(
"\nMemory usage statistics (detailed):\n" );
2390 " Module/Line Number Largest Total Unfreed \n" );
2391 for ( ms = mwStatList; ms; ms = ms->
next )
2393 if ( ms->
line == -1 )
2396 else modname = ms->
file;
2397 modnamelen = strlen( modname );
2398 if ( modnamelen > 42 ) { modname = modname + modnamelen - 42; }
2400 mwWrite(
" %-42s %-8ld %-8ld %-8ld %-8ld\n", modname, ms->
num, ms->
max, ms->
total,
2402 if ( ms->
file && mwStatLevel > 1 )
2404 for ( ms2 = mwStatList; ms2; ms2 = ms2->
next )
2406 if ( ms2->
line != -1 && ms2->
file != NULL && !mwStrCmpI( ms2->
file, ms->
file ) )
2408 mwWrite(
" %-8d %-8ld %-8ld %-8ld %-8ld\n",
2417static mwStat* mwStatGet(
const char*
file,
int line,
int makenew ) {
2420 if ( mwStatLevel < 2 ) line = -1;
2422 for ( ms = mwStatList; ms != NULL; ms = ms->
next )
2424 if ( line != ms->
line )
continue;
2427 if ( ms->
file == NULL )
break;
2430 if ( ms->
file == NULL )
continue;
2431 if ( !strcmp( ms->
file,
file ) )
break;
2434 if ( ms != NULL )
return ms;
2436 if ( !makenew )
return NULL;
2441 if ( mwFreeUp(
sizeof(
mwStat ), 0 ) <
sizeof(
mwStat ) ||
2444 mwWrite(
"internal: memory low, statistics incomplete for '%s'\n",
file );
2454 ms->
next = mwStatList;
2459static void mwStatAlloc(
size_t size,
const char*
file,
int line ) {
2463 ms = mwStatGet(
file, -1, 1 );
2466 ms->
total += (long)size;
2467 ms->
curr += (long)size;
2473 if ( mwStatLevel > 1 && line != -1 &&
file )
2475 ms = mwStatGet(
file, line, 1 );
2478 ms->
total += (long)size;
2479 ms->
curr += (long)size;
2486static void mwStatFree(
size_t size,
const char*
file,
int line ) {
2490 ms = mwStatGet(
file, -1, 1 );
2491 if ( ms != NULL ) ms->
curr -= (long)size;
2494 if ( mwStatLevel > 1 && line != -1 &&
file )
2496 ms = mwStatGet(
file, line, 1 );
2497 if ( ms != NULL ) ms->
curr -= (long)size;
2509static char mwDummy(
char c ) {
return c; }
2514# define WIN32_LEAN_AND_MEAN
2515# include <windows.h>
2517 if ( p == NULL )
return 0;
2518 if ( IsBadReadPtr( p, len ) )
return 0;
2524 if ( p == NULL )
return 0;
2525 if ( IsBadReadPtr( p, len ) || IsBadWritePtr( p, len ) )
return 0;
2535typedef void ( *mwSignalHandlerPtr )( int );
2536mwSignalHandlerPtr mwOldSIGSEGV = (mwSignalHandlerPtr)0;
2537jmp_buf mwSIGSEGVjump;
2538static void mwSIGSEGV(
int n );
2540static void mwSIGSEGV(
int n ) {
2542 longjmp( mwSIGSEGVjump, 1 );
2548 if ( p == NULL )
return 0;
2549 if ( !len )
return 1;
2552 mwOldSIGSEGV = signal( SIGSEGV, mwSIGSEGV );
2554 if ( setjmp( mwSIGSEGVjump ) )
2556 signal( SIGSEGV, mwOldSIGSEGV );
2561 ptr = (
const char*)p;
2571 if ( *ptr == 0x7C ) (void)mwDummy( (
char)0 );
2572 }
while ( (
const void*)ptr != p );
2575 signal( SIGSEGV, mwOldSIGSEGV );
2582 if ( p == NULL )
return 0;
2583 if ( !len )
return 1;
2586 mwOldSIGSEGV = signal( SIGSEGV, mwSIGSEGV );
2588 if ( setjmp( mwSIGSEGVjump ) )
2590 signal( SIGSEGV, mwOldSIGSEGV );
2605 *ptr = mwDummy( *ptr );
2606 }
while ( (
void*)ptr != p );
2609 signal( SIGSEGV, mwOldSIGSEGV );
2618 if ( p == NULL )
return 0;
2619 if ( len == 0 )
return 1;
2623 if ( p == NULL )
return 0;
2624 if ( len == 0 )
return 1;
2633#if defined( WIN32 ) || defined( __WIN32__ )
2635static void mwMutexInit(
void ) {
2636 mwGlobalMutex = CreateMutex( NULL, FALSE, NULL );
2640static void mwMutexTerm(
void ) {
2641 CloseHandle( mwGlobalMutex );
2645static void mwMutexLock(
void ) {
2646 if ( WaitForSingleObject( mwGlobalMutex, 1000 ) == WAIT_TIMEOUT )
2647 { mwWrite(
"mwMutexLock: timed out, possible deadlock\n" ); }
2651static void mwMutexUnlock(
void ) {
2652 ReleaseMutex( mwGlobalMutex );
2658#if defined( MW_PTHREADS ) || defined( HAVE_PTHREAD_H )
2660static void mwMutexInit(
void ) {
2661 pthread_mutex_init( &mwGlobalMutex, NULL );
2665static void mwMutexTerm(
void ) {
2666 pthread_mutex_destroy( &mwGlobalMutex );
2670static void mwMutexLock(
void ) {
2671 pthread_mutex_lock( &mwGlobalMutex );
2675static void mwMutexUnlock(
void ) {
2676 pthread_mutex_unlock( &mwGlobalMutex );
2689# ifndef MEMWATCH_NOCPP
2692const char *mwNFile = NULL;
2701MemWatch::MemWatch() {
2702 if( mwInited )
return;
2707MemWatch::~MemWatch() {
2708 if( mwUseAtexit )
return;
2716void*
operator new(
unsigned size ) {
2718 return mwMalloc( size,
"<unknown>", 0 );
2724void*
operator new(
unsigned size,
const char *
file,
int line ) {
2733void*
operator new[] (
unsigned size,
const char *
file,
int line ) {
2745void operator delete(
void *p ) {
2746 if( p == NULL )
return;
2752 mwFree( p, mwNFile, mwNLine );
2759void operator delete[](
void *p ) {
2760 if( p == NULL )
return;
2766 mwFree( p, mwNFile, mwNLine );
sprintf(cut, "kal_costheta0_em>-0.93&&kal_costheta0_em<0.93&&kal_pxy0_em>=0.05+%d*0.1&&kal_" "pxy0_em<0.15+%d*0.1&&NGch>=2", j, j)
EvtComplex exp(const EvtComplex &c)
DOUBLE_PRECISION count[3]
#define mwMark(p, t, f, n)
#define mwAssert(e, es, f, l)
#define mwVerify(e, es, f, l)
#define mwUnmark(p, f, n)
int mwIsReadAddr(const void *p, unsigned len)
#define mwMalloc(n, f, l)
#define mwRealloc(p, n, f, l)
#define mwTestBuffer(f, l, b)
const unsigned long mwCounter
#define mwCalloc(n, m, f, l)
int mwIsSafeAddr(void *p, unsigned len)
#define mwStrdup(p, f, l)
void mwNoMansLand(int level)
struct mwMarker_ mwMarker
#define MW_MUTEX_UNLOCK()
void mwAutoCheck(int onoff)
#define mwBUFFER_TO_MW(p)
void mwBreakOut(const char *cause)
int mwIsReadAddr(const void *p, unsigned len)
int mwIsSafeAddr(void *p, unsigned len)
void mwSetAriAction(int action)
struct mwGrabData_ mwGrabData
int mwAriHandler(const char *estr)
char blob[1024 - sizeof(mwGrabData *) - sizeof(int)]