memchk.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 278 行

CPP
278
字号
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <new.h>

#include "memchk.h"

#define MEMCHK_STATUS( e, s )	s,

static const char * const memchkErrorMessage[] = {
#include "memchkst.h"
};

#pragma initialize before library;

struct memory_block {
    unsigned		xor_ob;
    memory_block	*next;
    unsigned		xor_so;
    unsigned		owner;
    unsigned		xor_sb;
    unsigned		size;
    unsigned		xor_sbo;
    unsigned		bound;
    char		data[];
};

struct list_descriptor {
    memory_block	*list;
};

static list_descriptor simpleAlloc;
static list_descriptor arrayAlloc;

static unsigned allocCount;
static unsigned freeCount;

#define BOUND_CHECK	(-1)

// definitions for Hamming code verification
#define VP_SB_OK	0x01
#define VP_SO_OK	0x02
#define VP_OB_OK	0x04
#define VP_SBO_OK	0x08
#define VP_ALL_OK	0x0f
#define VP_NULL		0x00

#define VP_SIZE_ZAPPED	VP_OB_OK
#define VP_BOUND_ZAPPED	VP_SO_OK
#define VP_OWNER_ZAPPED	VP_SB_OK
#define VP_SBO_ZAPPED	(VP_OB_OK|VP_SO_OK|VP_SB_OK)
#define VP_SB_ZAPPED	(VP_OB_OK|VP_SO_OK|VP_SBO_OK)
#define VP_SO_ZAPPED	(VP_OB_OK|VP_SBO_OK|VP_SB_OK)
#define VP_OB_ZAPPED	(VP_SBO_OK|VP_SO_OK|VP_SB_OK)

void break_point( void )
{
    static char *p;
    *p = '\0';
}

extern "C" void MemCheckError( memcheck_error rc, unsigned aindex, int delta )
{
    FILE *fp;

    fprintf( stderr, "MEMCHK error: < %s > alloc #: %u delta: %d free #: %u\n",
	     memchkErrorMessage[ rc ], aindex, delta, freeCount );
    fp = fopen( "memchk.log", "w" );
    if( fp != NULL ) {
	fprintf( fp, "MEMCHK error: < %s > alloc #: %u delta: %d free #: %u\n",
		 memchkErrorMessage[ rc ], aindex, delta, freeCount );
	fclose( fp );
    }
    break_point();
}

static void *memchkAlloc( list_descriptor *kind, size_t amt )
{

    if( amt == 0 ) {
	amt = sizeof( int );
    }
    amt += sizeof( int ) - 1;
    amt &= ~( sizeof( int ) - 1 );
    size_t size = amt;
    amt += sizeof( unsigned );
    amt += sizeof( memory_block );
    memory_block *e = (memory_block *) malloc( amt );
    if( e == NULL ) {
	return( e );
    }
    memset( e, 0xaa, _msize( e ) );
    unsigned *end_check = (unsigned *) ( e->data + size );
    *end_check = BOUND_CHECK ^ size;
    e->next = kind->list;
    e->bound = BOUND_CHECK ^ -size;
    e->owner = ++allocCount;
    e->size = size;
    e->xor_sbo = e->size ^ e->bound ^ e->owner;
    e->xor_sb = e->size ^ e->bound;
    e->xor_so = e->size ^ e->owner;
    e->xor_ob = e->bound ^ e->owner;
    kind->list = e;
    return( e->data );
}

static int verifyBlock( memory_block *e, list_descriptor *kind )
{
    int delta;
    unsigned valid_parts;
    unsigned owner;
    unsigned *end_check;

    valid_parts = VP_NULL;
    if( e->xor_sb == ( e->size ^ e->bound ) ) {
	valid_parts |= VP_SB_OK;
    }
    if( e->xor_so == ( e->size ^ e->owner ) ) {
	valid_parts |= VP_SO_OK;
    }
    if( e->xor_ob == ( e->owner ^ e->bound ) ) {
	valid_parts |= VP_OB_OK;
    }
    if( e->xor_sbo == ( e->size ^ e->bound ^ e->owner ) ) {
	valid_parts |= VP_SBO_OK;
    }
    delta = -offsetof( memory_block, data );
    switch( valid_parts ) {
    case VP_ALL_OK:
	break;
    case VP_SIZE_ZAPPED:
	delta += offsetof( memory_block, size );
	MemCheckError( MC_CHECKSUM_ERROR, e->owner, delta );
	return( 1 );
	break;
    case VP_BOUND_ZAPPED:
	delta += offsetof( memory_block, bound );
	MemCheckError( MC_CHECKSUM_ERROR, e->owner, delta );
	return( 1 );
    case VP_OWNER_ZAPPED:
	delta += offsetof( memory_block, owner );
	// recover owner if possible
	owner = e->xor_sbo ^ e->size ^ e->bound;
	if( owner != ( e->xor_so ^ e->size ) ) {
	    owner = 0;
	}
	if( owner != ( e->xor_ob ^ e->bound ) ) {
	    owner = 0;
	}
	MemCheckError( MC_CHECKSUM_ERROR, owner, delta );
	return( 1 );
    case VP_SBO_ZAPPED:
	delta += offsetof( memory_block, xor_sbo );
	MemCheckError( MC_CHECKSUM_ERROR, e->owner, delta );
	return( 1 );
    case VP_SB_ZAPPED:
	delta += offsetof( memory_block, xor_sb );
	MemCheckError( MC_CHECKSUM_ERROR, e->owner, delta );
	return( 1 );
    case VP_SO_ZAPPED:
	delta += offsetof( memory_block, xor_so );
	MemCheckError( MC_CHECKSUM_ERROR, e->owner, delta );
	return( 1 );
    case VP_OB_ZAPPED:
	delta += offsetof( memory_block, xor_ob );
	MemCheckError( MC_CHECKSUM_ERROR, e->owner, delta );
	return( 1 );
    default:
	MemCheckError( MC_CHECKSUM_ERROR, 0, 0 );
	return( 1 );
    }
    if( e->bound != ( BOUND_CHECK ^ -e->size ) ) {
	delta += offsetof( memory_block, bound );
	MemCheckError( MC_LO_BOUND_ERROR, e->owner, delta );
	return( 1 );
    }
    end_check = (unsigned *) ( e->data + e->size );
    if( *end_check != ( BOUND_CHECK ^ e->size ) ) {
	MemCheckError( MC_HI_BOUND_ERROR, e->owner, e->size );
	return( 1 );
    }
    return( 0 );
}

static memory_block *findAlloc( list_descriptor *kind, memory_block *b )
{
    memory_block *c;

    for( c = kind->list; c != NULL; c = c->next ) {
	if( c == b ) {
	    return( c );
	}
    }
    return( NULL );
}

static void memchkFree( list_descriptor *kind, void *p, list_descriptor *other_kind,
			 memcheck_error other_error )
{
    memory_block *e;
    memory_block *f;
    memory_block *c;
    memory_block **u;

    ++freeCount;
    if( p == NULL ) {
	return;
    }
    u = &(kind->list);
    e = (memory_block *)(((char *)p) - offsetof( memory_block, data ));
    for( c = *u; c != NULL; c = c->next ) {
	if( c == e ) break;
	u = &(c->next);
    }
    if( c == NULL ) {
	if( findAlloc( other_kind, e ) != NULL ) {
	    MemCheckError( other_error, e->owner, 0 );
	} else {
	    MemCheckError( MC_FREE_UNALLOC_ERROR, e->owner, 0 );
	}
	verifyBlock( e, kind );
	return;
    }
    if( verifyBlock( e, kind ) ) {
	return;
    }
    *u = e->next;
    if( u != &(kind->list) ) {
	f = (memory_block *)(((char *)u) - offsetof( memory_block, next ));
	if( verifyBlock( f, kind ) ) {
	    return;
	}
    }
    memset( e, 0xdd, _msize( e ) );
    free( e );
}

void *operator new( size_t amt )
{
    return( memchkAlloc( &simpleAlloc, amt ) );
}

void operator delete( void *p )
{
    memchkFree( &simpleAlloc, p, &arrayAlloc, MC_ARRAY_SIMPLE_ERROR );
}

#if __WATCOMC__ > 950
void *operator new []( size_t amt )
{
    return( memchkAlloc( &arrayAlloc, amt ) );
}

void operator delete []( void *p )
{
    memchkFree( &arrayAlloc, p, &simpleAlloc, MC_SIMPLE_ARRAY_ERROR );
}
#endif

#ifdef TEST
int main()
{
    char *p1 = new char;
    char *p2 = new char[10];
    char *p3 = new char;
    char *h = p1 + offsetof( memory_block, xor_ob );
    h -= offsetof( memory_block, data );
    // *h = '@';
    //memset( p2, 0, 20 );
    delete p1;
    delete [] p2;
    delete p2;
    delete [] p3;
    return 0;
}
#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?