ma_test.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,089 行 · 第 1/3 页
C
1,089 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Heap management functions test.
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <conio.h>
#ifdef __SW_BW
#include <wdefwin.h>
#endif
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define ARGLENGTH 256
#define DOT_INTERVAL 512
#define WSIZE sizeof(int)
#define SIZE_MARGIN 16
#define TEST_PASS 0
#define TEST_FAIL 1
#define TEST_NOMEM 2
#define TEST_NOSEG 3
#define TYPE_DEFAULT 0
#define TYPE_NEAR 1
#define TYPE_FAR 2
#define TYPE_BASED 3
#define TYPE_HUGE 4
#define FREED_BEFORE 0
#define FREED_AFTER 1
#define INTERNAL_ERR 255
#if !defined(__386__) && !defined(__AXP__) // Only appropriate to 16-bit versions
#define HUGE_NUM_EL 16384 // Must be a power of 2
#endif
#define NUM_EL 8175 // For double, 8175 * 8 = 65400 < 64k
// Note that NUM_EL has to be < 8192. Otherwise, we get overflow when
// calling malloc( NUM_EL * sizeof( double ) ).
#define BASED_HEAP_SIZE 512
// Casting _NULLOFF to long produces 0xFFFFFFFF, while casting the return of
// failing based heap routines to long produces 0xFFFF. At this point it is
// unclear whether that is a compiler bug, whether the _NULLOFF macro is wrong,
// or whether the test makes bad assumptions. For the moment, get around it
// by casting to unsigned in a few specific cases. This hack should be removed
// when it is determined what's actually wrong and the original problem fixed.
#define HACK_CAST (unsigned)
// This is a macro performing everything needed before returning the call
#if defined(__386__) || defined(__AXP__)
#define _CRET() { \
if( doheapwlk ) AskHeapWlk( FREED_BEFORE, type, __LINE__ ); \
if( type == TYPE_DEFAULT ) { \
free( (char *) ptr_char ); \
free( (int *) ptr_int ); \
free( (double *) ptr_double ); \
} else if( type == TYPE_NEAR ) { \
_nfree( (char __near *) ptr_char ); \
_nfree( (int __near *) ptr_int ); \
_nfree( (double __near *) ptr_double ); \
} \
if( doheapwlk ) AskHeapWlk( FREED_AFTER, type, __LINE__ ); \
memavail = _memavl(); \
return; \
}
#else
#define _CRET() { \
if( doheapwlk ) AskHeapWlk( FREED_BEFORE, type, __LINE__ ); \
if( type == TYPE_DEFAULT ) { \
free( (void *) ptr_char ); \
free( (void *) ptr_int ); \
free( (void *) ptr_double ); \
} else if( type == TYPE_NEAR ) { \
_nfree( (void __near *) ptr_char ); \
_nfree( (void __near *) ptr_int ); \
_nfree( (void __near *) ptr_double ); \
} else if( type == TYPE_FAR ) { \
_ffree( (void __far *) ptr_char ); \
_ffree( (void __far *) ptr_int ); \
_ffree( (void __far *) ptr_double ); \
} else if( type == TYPE_BASED ) { \
_DOBFREE(); \
} else if( type == TYPE_HUGE ) { \
hfree( (void __huge *) ptr_char ); \
hfree( (void __huge *) ptr_int ); \
hfree( (void __huge *) ptr_double ); \
} \
if( doheapwlk ) AskHeapWlk( FREED_AFTER, type, __LINE__ ); \
memavail = _memavl(); \
return; \
}
#endif
// _NUL combines NULL and _NULLOFF
#if defined( __AXP__ ) || defined( __UNIX__ )
#define _NUL NULL
#else
#define _NUL (type == TYPE_BASED ? (long)_NULLOFF: (long)NULL)
#endif
// Macro to free based pointers and the corresponding segment
#define _DOBFREE() { \
if( (char __based(seg)*)ptr_char != _NULLOFF ) { \
_bfree( seg, (char __based(seg)*)ptr_char ); \
} \
if( (int __based(seg)*)ptr_int != _NULLOFF ) { \
_bfree( seg,(int __based(seg)*)ptr_int ); \
} \
if( (double __based(seg)*)ptr_double != _NULLOFF ) { \
_bfree( seg,(double __based(seg)*)ptr_double); \
} \
}
typedef struct _test_result {
char funcname[80];
int status;
char msg[256];
} test_result;
#if !defined(__WINDOWS__) && !defined(__386__) && !defined(__AXP__)
size_t memrecord;
#endif
size_t memavail;
int more_debug = FALSE;
int nomem_lineno = 0;
int noseg_lineno = 0;
int dotrace = FALSE;
int dopause = FALSE;
int tracethisloop;
int doheapwlk = FALSE;
#if !defined(__386__) && !defined(__AXP__)
__segment seg = _NULLSEG;
#endif
static const char *errmsg[] = {
"ABLE TO ALLOCATE MORE THAN ALL OF THE AVAILABLE STACK", // 0
"CANNOT ALLOCATE HALF OF THE AVAILABLE STACK", // 1
"RETURNED NULL FOR char BUT SUCCEEDED FOR int OR double", // 2
"RETURNED NULL FOR int BUT SUCCEEDED FOR double", // 3
"NOT ABLE TO CLEAR THE ALLOCATED MEMORY (SET TO ZERO)", // 4
"NOT ABLE TO REALLOCATE HALF THE ORIGINAL MEMORY BLOCK", // 5
"CONTENT OF THE REALLOCATED MEMORY IS ALTERED", // 6
"_memavl() RETURNED A VALUE WHICH IS LESS THAN _memmax()", // 7
"NEAR AVAILABLE HEAP SHRINKED AFTER THIS FUNCTION CALL", // 8
"RETURNED VALUE IS INCORRECT", // 9
"REPORTED THAT LESS THAN 1 DOUBLE CAN BE ALLOCATED, BUG?", // 10
"CANNOT ALLOCATE THE RETURNED NUMBER OF DOUBLES", // 11
"UNABLE TO ALLOCATE MEMORY OF SIZE SPECIFIED BY _memmax()", // 12
"VALUES RETURNED BY _memmax() are inconsistant", // 13
"SUCCEEDED IN ALLOCATING MORE THAN AVAILABLE HEAP", // 14
"NOT ABLE TO EXPAND THE BLOCK BACK TO THE SIZE IT WAS BEFORE", // 15
"FAILED IN ALLOCATING MEMORY FROM A FAR HEAP", // 16
"FAILED IN ALLOCATING MEMORY FROM A 32-BIT NEAR HEAP", // 17
"FREE NEAR HEAP HAS SHRUNK AFTER ALLOCATING MEMORY FROM A FAR HEAP" // 18
};
void ShowDot( int ctr )
{
if( ( ctr % DOT_INTERVAL ) == 0 ) putch( '.' );
}
void AskHeapWlk( int timing, int type, int lineno )
{
char ans;
if( type == TYPE_HUGE ) return; // No huge _heapwalk()
cprintf( "[-h] Dump the heap %s freeing? ",
(timing == FREED_BEFORE ) ? "before" : "after" );
ans = getche();
cprintf( "\n\r" );
if( ans == 'y' || ans == 'Y' ) {
struct _heapinfo h_info;
int heap_status;
h_info._pentry = NULL;
printf( "-----------------------------------------\n" );
printf( "Heap walk result (%s freeing memory):\n",
(timing == FREED_BEFORE ) ? "before" : "after" );
for( ;; ) {
switch( type ) {
case TYPE_DEFAULT:
heap_status = _heapwalk( &h_info );
break;
case TYPE_NEAR:
heap_status = _nheapwalk( &h_info );
break;
#if !defined(__386__) && !defined(__AXP__)
case TYPE_FAR:
heap_status = _fheapwalk( &h_info );
break;
case TYPE_BASED:
heap_status = _bheapwalk( seg, &h_info );
break;
#endif
default:
heap_status = INTERNAL_ERR;
break;
}
if( heap_status != _HEAPOK ) break;
printf( " %s block at %Fp of size %4.4X\n",
( h_info._useflag == _USEDENTRY ? "USED" : "FREE" ),
h_info._pentry, h_info._size );
}
switch( heap_status ) {
case _HEAPEND:
printf( "OK - end of heap\n" );
break;
case _HEAPEMPTY:
printf( "OK - heap is empty\n" );
break;
case _HEAPBADBEGIN:
printf( "ERROR - heap is damaged\n" );
printf( "Reference: line #%d in source.\n", lineno );
break;
case _HEAPBADPTR:
printf( "ERROR - bad pointer to heap\n" );
printf( "Reference: line #%d in source.\n", lineno );
break;
case _HEAPBADNODE:
printf( "ERROR - bad node in heap\n" );
printf( "Reference: line #%d in source.\n", lineno );
break;
case INTERNAL_ERR:
printf( "INTERNAL ERROR - unrecognized heap type\n" );
break;
default:
break;
}
printf( "-----------------------------------------\n" );
}
}
void Test_alloca_stackavail__memavl__memmax( test_result *result )
{
size_t ctr, buffsize, memsize;
char *buffer;
char __near *near_buffer;
if( more_debug ) {
printf( "Testing: alloca(), stackavail(), " );
printf( "_memavl(), _memmax()...\n" );
}
strcpy( result->funcname,"_memavl() or _memmax()" );
memsize = _memmax();
if( _memavl() < memsize ) {
result->status = TEST_FAIL;
strcpy( result->msg, errmsg[7] );
return;
}
near_buffer = (char __near *) _nmalloc( memsize );
if( near_buffer == NULL ) {
strcpy( result->funcname, "_memmax() or _nmalloc()" );
result->status = TEST_FAIL;
strcpy( result->msg, errmsg[12] );
return;
}
_nfree( near_buffer );
if( memsize != _memmax() ) {
strcpy( result->funcname, "_memmax() or _nfree()" );
result->status = TEST_FAIL;
strcpy( result->msg, errmsg[13] );
return;
}
memsize = _memavl();
strcpy( result->funcname,"stackavail() and/or alloca()" );
buffsize = stackavail() + 1;
buffer = alloca( buffsize ); // Allocate more than available stack size
if( buffer != NULL ) {
result->status = TEST_FAIL;
strcpy( result->msg, errmsg[0] );
return;
}
buffsize = stackavail() >> 1;
buffer = alloca( buffsize ); // Allocate half of available stack size
if( buffer == NULL ) {
result->status = TEST_FAIL;
strcpy( result->msg, errmsg[1] );
return;
}
if( _memavl() < memsize ) {
result->status = TEST_FAIL;
strcpy( result->msg, errmsg[8] );
}
tracethisloop = AskTrace( result->funcname, __LINE__ );
for( ctr = 0; ctr < buffsize; ++ctr ) {
*(buffer + ctr) = 6;
if( tracethisloop ) ShowDot( ctr );
} // Make sure that the buffer is accessible before returning
if( tracethisloop ) cprintf( "\r\nTrace done. No problems detected.\r\n");
result->status = TEST_PASS;
}
void Test_calloc__msize( test_result *result, int type )
{
long ptr_char = NULL;
long ptr_int = NULL;
long ptr_double = NULL;
size_t ctr, size, retsize, chkmemavl;
switch( type ) {
case TYPE_DEFAULT:
if( more_debug ) {
printf( "Testing: calloc(), msize()...\n" );
}
strcpy( result->funcname,"calloc()" );
ptr_char = (long) calloc( NUM_EL, sizeof( char ) );
ptr_int = (long) calloc( NUM_EL, sizeof( int ) );
chkmemavl = _memavl();
ptr_double = (long) calloc( NUM_EL, sizeof( double ) );
break;
case TYPE_NEAR:
if( more_debug ) {
printf( "Testing: _ncalloc(), _nmsize()...\n" );
}
strcpy( result->funcname,"_ncalloc()" );
ptr_char = (long) _ncalloc( NUM_EL, sizeof( char ) );
ptr_int = (long) _ncalloc( NUM_EL, sizeof( int ) );
ptr_double = (long) _ncalloc( NUM_EL, sizeof( double ) );
break;
#if !defined(__386__) && !defined(__AXP__)
case TYPE_FAR:
if( more_debug ) {
printf( "Testing: _fcalloc(), _fmsize()...\n" );
}
strcpy( result->funcname,"_fcalloc()" );
ptr_char = (long) _fcalloc( NUM_EL, sizeof( char ) );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?