Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/hprof/debug_malloc.c
38829 views
/*1* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/383940/* **************************************************************************41*42* Set of malloc/realloc/calloc/strdup/free replacement macros that43* insert some extra words around each allocation for debugging purposes44* and also attempt to detect invalid uses of the malloc heap through45* various tricks like inserting clobber words at the head and tail of46* the user's area, delayed free() calls, and setting the memory to47* a fixed pattern on allocation and when freed. The allocations also48* can include warrants so that when an area is clobbered, this49* package can report where the allocation took place.50* The macros included are:51* malloc(size)52* realloc(ptr,size)53* calloc(nelem,elsize)54* strdup(s1)55* free(ptr)56* malloc_police() <--- Not a system function57* The above macros match the standard behavior of the system functions.58*59* They should be used through the include file "debug_malloc.h".60*61* IMPORTANT: All source files that call any of these macros62* should include debug_malloc.h. This package will63* not work if the memory isn't allocated and freed64* by the macros in debug_malloc.h. The important issue65* is that any malloc() from debug_malloc.h must be66* freed by the free() in debug_malloc.h.67*68* The macros in debug_malloc.h will override the normal use of69* malloc, realloc, calloc, strdup, and free with the functions below.70*71* These functions include:72* void *debug_malloc(size_t, void*, int);73* void *debug_realloc(void*, size_t, void*, int);74* void *debug_calloc(size_t, size_t, void*, int);75* void debug_free(void *, void*, int);76*77* In addition the function debug_malloc_police() can be called to78* tell you what memory has not been freed.79* void debug_malloc_police(void*, int);80* The function debug_malloc_police() is available through the macro81* malloc_police(). Normally you would want to call this at exit()82* time to find out what memory is still allocated.83*84* The variable malloc_watch determines if the warrants are generated.85* warrants are structures that include the filename and line number86* of the caller who allocated the memory. This structure is stored87* at the tail of the malloc space, which is allocated large enough88* to hold some clobber words at the head and tail, the user's request89* and the warrant record (if malloc_watch is non-zero).90*91* The macro LEFT_OVER_CHAR is what the trailing bytes of an allocation92* are set to (when the allocation is not a multiple of 8) on allocation.93* At free(0 time, these bytes are double checked to make sure they were94* not clobbered. To remove this feature #undef LEFT_OVER_CHAR.95*96* The memory freed will have the FREED_CHAR put into it. To remove this97* feature #undef FREED_CHAR.98*99* The memory allocated (not calloc'd) will have the ALLOC_CHAR put into it100* at the time of allocation. To remove this feature #undef ALLOC_CHAR.101*102* The macro MAX_FREE_DELAY_COUNT controls how many free blocks will103* be kept around before being freed. This creates a delayed affect104* so that free space that gets clobbered just might get detected.105* The free() call will immediately set the user space to the FREED_CHAR,106* leaving the clobber words and warrant in place (making sure they107* haven't been clobbered). Then the free() pointer is added to a108* queue of MAX_FREE_DELAY_COUNT long, and if the queue was full, the109* oldest free()'d memory is actually freed, getting it's entire110* memory length set to the FREED_CHAR.111*112* WARNING: This can significantly slow down an application, depending113* on how many allocations are made. Also the additional memory114* needed for the clobber words and the warrants can be significant115* again, depending on how many allocations are made.116* In addition, the delayed free calls can create situations117* where you might run out of memory prematurely.118*119* **************************************************************************120*/121122#ifdef DEBUG123124#include <stdio.h>125#include <stdlib.h>126#include <string.h>127#include <ctype.h>128#include <stdarg.h>129#include "hprof.h"130131/* ***************************************************************************132* Space normally looks like (clobber Word is 64 bits and aligned to 8 bytes):133*134* -----------------135* malloc/free get->| clobber Word | ---> contains -size requested by user136* -----------------137* User gets --->| user space |138* | |139* | | left_over | ---> left_over bytes will be <= 7140* -----------------141* | clobber Word | ---> contains -size requested by user142* -----------------143* | Warrant | ---> Optional (malloc_watch!=0)144* | | Contains filename and line number145* | | where allocation happened146* | |147* -----------------148***************************************************************************/149150/*151* Flag that tells debug_malloc/debug_free/debug_realloc to police152* heap space usage. (This is a dynamic flag that can be turned on/off)153*/154static int malloc_watch = 1;155156/* Character to stuff into freed space */157#define FREED_CHAR 'F'158159/* Character to stuff into allocated space */160#define ALLOC_CHAR 'A'161162/* Character to stuff into left over trailing bytes */163#define LEFT_OVER_CHAR 'Z'164165/* Number of 'free' calls that will be delayed until the end */166#define MAX_FREE_DELAY_COUNT 1167#undef MAX_FREE_DELAY_COUNT168169/* Maximum name of __FILE_ stored in each malloc'd area */170#define WARRANT_NAME_MAX (32-1) /* 1 less than multiple of 8 is best */171172/* Macro to convert a user pointer to the malloc pointer */173#define user2malloc_(uptr) (((char*)(void*)uptr)-sizeof(Word))174175/* Macro to convert a macro pointer to the user pointer */176#define malloc2user_(mptr) (((char*)(void*)(mptr))+sizeof(Word))177178/* Size of the warrant record (this is dynamic) */179#define warrant_space ( malloc_watch?sizeof(Warrant_Record):0 )180181/* Macro to round up a number of bytes to a multiple of sizeof(Word) bytes */182#define round_up_(n) \183((n)==0?0:(sizeof(Word)+(((n)-1)/sizeof(Word))*sizeof(Word)))184185/* Macro to calculate the needed malloc bytes from the user's request. */186#define rbytes_(nbytes) \187(size_t)( sizeof(Word) + round_up_(nbytes) + sizeof(Word) + warrant_space )188189/* Macro to get the -size stored in space through the malloc pointer */190#define nsize1_(mptr) (((Word*)(void*)(mptr))->nsize1)191#define nsize2_(mptr) (((Word*)(void*)(mptr))->nsize2)192193/* Macro to get the -size stored in the tail of the space through */194/* the malloc pointer */195#define tail_nsize1_(mptr) \196nsize1_(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word))197#define tail_nsize2_(mptr) \198nsize2_(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word))199200/* Macro to get the -size stored in space through the user pointer */201#define user_nsize1_(uptr) nsize1_(user2malloc_(uptr))202#define user_nsize2_(uptr) nsize2_(user2malloc_(uptr))203204/* Macro to get the -size stored in the tail of the space through */205/* the user pointer */206#define user_tail_nsize1_(uptr) tail_nsize1_(user2malloc_(uptr))207#define user_tail_nsize2_(uptr) tail_nsize2_(user2malloc_(uptr))208209/* Macro to get the int* of the last 32bit word of user space */210#define last_user_word_(mptr) \211((int*)(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))))212213/* Macros to get at the warrant contents from the malloc pointer */214#define warrant_(mptr) \215(*((Warrant_Record*)(void*)(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word)*2)))216217/* This struct is allocated after the tail clobber word if malloc_watch */218/* is true. */219typedef struct {220void *link; /* Next mptr in list */221char name[WARRANT_NAME_MAX + 1]; /* Name of allocator */222int line; /* Line number where allocated */223int id; /* Nth allocation */224} Warrant_Record;225#define warrant_link_(mptr) warrant_(mptr).link226#define warrant_name_(mptr) warrant_(mptr).name227#define warrant_line_(mptr) warrant_(mptr).line228#define warrant_id_(mptr) warrant_(mptr).id229#define MFILE(mptr) (malloc_watch?warrant_name_(mptr):"?")230#define MLINE(mptr) (malloc_watch?warrant_line_(mptr):0)231#define MID(mptr) (malloc_watch?warrant_id_(mptr):0)232233/* This should be one machine word and is also the clobber word struct */234typedef struct {235int nsize1;236int nsize2;237} Word; /* Largest basic type , sizeof(double)? */238239/* The first malloc pointer for the warrants */240static void *first_warrant_mptr = NULL;241242/* Counter of allocations */243static int id_counter = 0;244static int largest_size = 0;245static void * largest_addr = NULL;246static void * smallest_addr = NULL;247248/* Used to isolate what the error is */249static char *debug_check;250static void *clobbered_ptr;251252/* Minimum macro */253#define minimum(a,b) ((a)<(b)?(a):(b))254255/* Message routine */256static void257error_message(const char * format, ...)258{259FILE *error_fp = stderr; /* All debug_malloc.c messages */260va_list ap;261va_start(ap, format);262(void)fprintf(error_fp, "debug_malloc: ");263(void)vfprintf(error_fp, format, ap);264(void)fprintf(error_fp, "\n");265(void)fflush(error_fp);266va_end(ap);267}268269/* This function prints out a memory error for the memory function270* 'name' which was called in file 'file' at line number 'line'. The malloc271* pointer with the error is in 'mptr'.272*/273static void274memory_error(void *mptr, const char *name, int mid, const char *mfile, int mline, const char *file, int line)275{276char nice_words[512];277char temp[256];278int len;279void *mptr_walk;280281if (name == NULL)282name = "UNKNOWN_NAME";283if (file == NULL)284file = "UNKNOWN_FILE";285md_system_error(temp, (int)sizeof(temp));286(void)strcpy(nice_words, temp);287if ( debug_check!=NULL ) {288(void)md_snprintf(nice_words, sizeof(nice_words),289"%s The %s at %p appears to have been hit.",290temp, debug_check, clobbered_ptr);291}292len = -nsize1_(mptr);293error_message("Error: "294"%s The malloc space #%d is at %p [user size=%d(0x%x)],"295" and was allocated from file \"%s\" at line %d."296" [The debug function %s() detected this error "297"in file \"%s\" at line %d.]",298nice_words, mid, mptr, len, len, mfile, mline,299name, file, line);300301/* Print out contents of this allocation */302{303int i;304void *uptr = malloc2user_(mptr);305char *pmess;306pmess = temp;307for(i=0;i<(int)sizeof(temp);i++) {308int ch = ((unsigned char*)uptr)[i];309if ( isprint(ch) ) {310*pmess++ = ch;311} else {312*pmess++ = '\\';313*pmess++ = 'x';314(void)sprintf(pmess,"%02x",ch);315pmess+=2;316}317}318*pmess = 0;319error_message("Error: %p contains user data: %s", uptr, temp);320}321322/* Try and print out table */323if (!malloc_watch) {324return;325}326mptr_walk = first_warrant_mptr;327if (mptr_walk != NULL) {328error_message("Active allocations: "329"count=%d, largest_size=%d, address range (%p,%p)",330id_counter, largest_size, smallest_addr, largest_addr);331do {332int size1;333int size2;334char *mfile_walk;335336if ( mptr_walk > largest_addr || mptr_walk < smallest_addr ) {337error_message("Terminating list due to pointer corruption");338break;339}340size1 = -nsize1_(mptr_walk);341size2 = -nsize2_(mptr_walk);342mfile_walk = MFILE(mptr_walk);343error_message("#%d: addr=%p size1=%d size2=%d file=\"%.*s\" line=%d",344MID(mptr_walk), mptr_walk, size1, size2,345WARRANT_NAME_MAX, mfile_walk, MLINE(mptr_walk));346if ( size1 != size2 || size1 > largest_size || size1 < 0 ) {347error_message("Terminating list due to size corruption");348break;349}350mptr_walk = warrant_link_(mptr_walk);351} while (mptr_walk != NULL);352}353abort();354}355356/* This function sets the clobber word and sets up the warrant for the input357* malloc pointer "mptr".358*/359static void360setup_space_and_issue_warrant(void *mptr, size_t size, const char *file, int line)361{362register int nbytes;363364/*LINTED*/365nbytes = (int)size;366if ( nbytes > largest_size || largest_addr == NULL ) largest_size = nbytes;367/*LINTED*/368if ( mptr > largest_addr ) largest_addr = mptr;369/*LINTED*/370if ( mptr < smallest_addr || smallest_addr == NULL ) smallest_addr = mptr;371372/* Must be done first: */373nsize1_(mptr) = -nbytes;374nsize2_(mptr) = -nbytes;375tail_nsize1_(mptr) = -nbytes;376tail_nsize2_(mptr) = -nbytes;377378#ifdef LEFT_OVER_CHAR379/* Fill in those few extra bytes just before the tail Word structure */380{381register int trailing_extra_bytes;382/* LINTED */383trailing_extra_bytes = (int) (round_up_(nbytes) - nbytes);384if ( trailing_extra_bytes > 0 ) {385register char *p;386register int i;387p = ((char *) mptr) + sizeof(Word) + nbytes;388for (i = 0; i < trailing_extra_bytes; i++)389p[i] = LEFT_OVER_CHAR;390}391}392#endif393394/* Fill out warrant */395if (malloc_watch) {396static Warrant_Record zero_warrant;397register void *p1,398*p2;399size_t len;400int start_pos = 0;401warrant_(mptr) = zero_warrant;402p1 = warrant_name_(mptr);403len = strlen(file);404if ( len > WARRANT_NAME_MAX ) {405/*LINTED*/406start_pos = (int)len - WARRANT_NAME_MAX;407}408p2 = ((char*)file) + start_pos;409/*LINTED*/410(void) memcpy(p1, p2, minimum(((int)len), WARRANT_NAME_MAX));411warrant_line_(mptr) = line;412warrant_id_(mptr) = ++id_counter;413warrant_link_(mptr) = first_warrant_mptr;414first_warrant_mptr = mptr;415}416}417418/* This function checks the clobber words at the beginning and end of the419* allocated space.420*/421static void422memory_check(void *uptr, int mid, const char *mfile, int mline, const char *file, int line)423{424int neg_nbytes;425int nbytes;426427debug_check = "pointer value itself";428clobbered_ptr = uptr;429if (uptr == NULL)430memory_error((void *) NULL, "memory_check", mid, mfile, mline, file, line);431432/* Check both Word structures */433434debug_check = "first beginning clobber word";435clobbered_ptr = (char*)&user_nsize1_(uptr);436neg_nbytes = user_nsize1_(uptr);437if (neg_nbytes >= 0)438memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);439440debug_check = "second beginning clobber word";441clobbered_ptr = (char*)&user_nsize2_(uptr);442if (neg_nbytes != user_nsize2_(uptr))443memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);444445debug_check = "first ending clobber word";446clobbered_ptr = (char*)&user_tail_nsize1_(uptr);447if (neg_nbytes != user_tail_nsize1_(uptr))448memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);449450debug_check = "second ending clobber word";451clobbered_ptr = (char*)&user_tail_nsize2_(uptr);452if (neg_nbytes != user_tail_nsize2_(uptr))453memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);454455/* Get a positive count of bytes */456nbytes = -neg_nbytes;457458#ifdef LEFT_OVER_CHAR459{460/* Check those few extra bytes just before the tail Word structure */461register int trailing_extra_bytes;462register int i;463register char *p;464/* LINTED */465trailing_extra_bytes = (int) (round_up_(nbytes) - nbytes);466p = ((char *) (uptr)) + nbytes;467debug_check = "trailing left over area";468for (i = 0; i < trailing_extra_bytes; i++) {469clobbered_ptr = p+1;470if (p[i] != LEFT_OVER_CHAR) {471memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line);472}473}474}475#endif476477/* Make sure debug_check is cleared */478debug_check = NULL;479}480481/* This function looks for the given malloc pointer in the police line up482* and removes it from the warrant list.483* mptr The pointer to the malloc space being removed484*/485static int486remove_warrant(void *mptr)487{488void *mptr1,489*last_mptr1;490491/* Free it up from the list */492if (malloc_watch && mptr != NULL) {493int found;494495found = 0;496last_mptr1 = NULL;497mptr1 = first_warrant_mptr;498while (mptr1 != NULL) {499if (mptr1 == mptr) {500if (last_mptr1 == NULL)501first_warrant_mptr = warrant_link_(mptr1);502else503warrant_link_(last_mptr1) = warrant_link_(mptr1);504found = 1;505break;506}507last_mptr1 = mptr1;508mptr1 = warrant_link_(mptr1);509}510return found;511}512return 1;513}514515static void516actual_free(void *uptr, const char *file, int line)517{518void *mptr;519const char *mfile;520int mline;521int mid;522if ( uptr == NULL )523return;524mptr = user2malloc_(uptr);525memory_check(uptr, (mid=MID(mptr)), (mfile=MFILE(mptr)), (mline=MLINE(mptr)), file, line);526if (malloc_watch && remove_warrant(mptr)==0 )527memory_check(uptr, mid, mfile, mline, file, line);528#ifdef FREED_CHAR529if ( mptr!=NULL ) {530size_t nbytes = -nsize1_(mptr);531/* LINTED */532(void)memset(mptr, FREED_CHAR, rbytes_(nbytes));533}534#endif535free(mptr);536}537538#ifdef MAX_FREE_DELAY_COUNT539540static void *free_delay[MAX_FREE_DELAY_COUNT];541static int free_delay_pos = 0;542543static void544delayed_free(void *uptr, const char* file, int line)545{546void *mptr;547void *olduptr = free_delay[free_delay_pos];548size_t nbytes;549if ( uptr==NULL )550return;551mptr = user2malloc_(uptr);552memory_check(uptr, MID(mptr), MFILE(mptr), MLINE(mptr), file, line);553if ( olduptr!=NULL ) {554actual_free(olduptr, file, line);555}556free_delay[free_delay_pos] = uptr;557free_delay_pos++;558free_delay_pos = free_delay_pos % MAX_FREE_DELAY_COUNT;559nbytes = -user_nsize1_(uptr);560#ifdef FREED_CHAR561(void)memset(uptr, FREED_CHAR, (size_t)nbytes);562#endif563}564565static void566delayed_free_all(const char *file, int line)567{568int i;569for ( i=0; i< MAX_FREE_DELAY_COUNT; i++) {570void *olduptr = free_delay[i];571free_delay[i] = NULL;572if ( olduptr!=NULL ) {573actual_free(olduptr, file, line);574}575}576}577578#endif579580void581debug_free(void *uptr, const char *file, int line)582{583int mid = 0;584585if (uptr == NULL)586memory_error((void *) NULL, "debug_free", mid, file, line, file, line);587#ifdef MAX_FREE_DELAY_COUNT588delayed_free(uptr, file, line);589#else590actual_free(uptr, file, line);591#endif592}593594/* This function calls malloc(). */595void *596debug_malloc(size_t nbytes, const char *file, int line)597{598void *mptr;599void *uptr;600int mid = id_counter;601602/*LINTED*/603if ((int)nbytes <= 0)604memory_error((void *) NULL, "debug_malloc", mid, file, line, file, line);605/* LINTED */606mptr = malloc(rbytes_(nbytes));607if (mptr == NULL)608memory_error((void *) NULL, "debug_malloc", mid, file, line, file, line);609setup_space_and_issue_warrant(mptr, nbytes, file, line);610uptr = malloc2user_(mptr);611#ifdef ALLOC_CHAR612(void)memset(uptr, ALLOC_CHAR, (size_t)nbytes);613#endif614return uptr;615}616617void *618debug_realloc(void *uptr, size_t nbytes, const char *file, int line)619{620void *mptr;621void *oldmptr;622void *newuptr;623size_t oldnbytes;624int mid = id_counter;625626oldmptr = user2malloc_(uptr);627oldnbytes = 0;628if ((int)nbytes <= 0)629memory_error(oldmptr, "debug_realloc", mid, file, line, file, line);630if (uptr != NULL) {631memory_check(uptr, MID(oldmptr), MFILE(oldmptr), MLINE(oldmptr), file, line);632oldnbytes = -user_nsize1_(uptr);633if ( malloc_watch && remove_warrant(oldmptr)==0 )634memory_check(uptr, MID(oldmptr), MFILE(oldmptr), MLINE(oldmptr), file, line);635}636if (uptr == NULL) {637/* LINTED */638mptr = malloc(rbytes_(nbytes));639} else {640/* LINTED */641mptr = realloc(oldmptr, rbytes_(nbytes));642}643if (mptr == NULL)644memory_error(oldmptr, "debug_realloc", mid, file, line, file, line);645setup_space_and_issue_warrant(mptr, nbytes, file, line);646newuptr = malloc2user_(mptr);647#ifdef ALLOC_CHAR648if (uptr == NULL)649(void)memset(newuptr, ALLOC_CHAR, (size_t)nbytes);650else if ( nbytes > oldnbytes )651(void)memset(((char*)newuptr)+oldnbytes, ALLOC_CHAR, (size_t)nbytes-oldnbytes);652#endif653return newuptr;654}655656/* This function calls calloc(). */657void *658debug_calloc(size_t nelem, size_t elsize, const char *file, int line)659{660void *mptr;661size_t nbytes;662int mid = id_counter;663664nbytes = nelem*elsize;665/*LINTED*/666if ((int)nbytes <= 0)667memory_error((void *) NULL, "debug_calloc", mid, file, line, file, line);668/* LINTED */669mptr = calloc(rbytes_(nbytes),1);670if (mptr == NULL)671memory_error((void *) NULL, "debug_calloc", mid, file, line, file, line);672setup_space_and_issue_warrant(mptr, nbytes, file, line);673return malloc2user_(mptr);674}675676/* This function replaces strdup(). */677char *678debug_strdup(const char *s1, const char *file, int line)679{680void *mptr;681void *uptr;682size_t nbytes;683int mid = id_counter;684685if (s1 == NULL)686memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line);687nbytes = strlen(s1)+1;688/*LINTED*/689if ((int)nbytes < 0)690memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line);691/* LINTED */692mptr = malloc(rbytes_(nbytes));693if (mptr == NULL)694memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line);695setup_space_and_issue_warrant(mptr, nbytes, file, line);696uptr = malloc2user_(mptr);697(void)strcpy((char*)uptr, s1);698return (char*)uptr;699}700701void702debug_malloc_verify(const char *file, int line)703{704void *mptr;705706#ifdef MAX_FREE_DELAY_COUNT707delayed_free_all(file,line);708#endif709710if (!malloc_watch) {711return;712}713mptr = first_warrant_mptr;714if (mptr != NULL) {715/* Check all this memory first */716do {717memory_check(malloc2user_(mptr), MID(mptr), MFILE(mptr), MLINE(mptr), file, line);718mptr = warrant_link_(mptr);719} while (mptr != NULL);720}721}722723/* Report outstanding space warrants to console. */724void725debug_malloc_police(const char *file, int line)726{727void *mptr;728729#ifdef MAX_FREE_DELAY_COUNT730delayed_free_all(file,line);731#endif732733if (!malloc_watch) {734return;735}736737mptr = first_warrant_mptr;738if (mptr != NULL) {739debug_malloc_verify(file, line);740/* Now issue warrants */741mptr = first_warrant_mptr;742do {743error_message("Outstanding space warrant: %p (%d bytes) allocated by %s at line %d, allocation #%d",744mptr, -nsize1_(mptr), warrant_name_(mptr),745warrant_line_(mptr), warrant_id_(mptr));746747mptr = warrant_link_(mptr);748} while (mptr != NULL);749}750}751752#else753754void755debug_malloc_verify(const char *file, int line)756{757file = file;758line = line;759}760761void762debug_malloc_police(const char *file, int line)763{764file = file;765line = line;766}767768#endif769770771