
								SMT 910213

   		      Error Checking Malloc Package
		      -----------------------------

	GENERAL DESCRIPTION
	-------------------

	This file describes the Error Checking Malloc Package, created
	to debug memory leaks in the Motif source code.

	The package is essentially a wrapper around XtMalloc, XtCalloc,
	XtRealloc, XtFree and the string and memory functions.  Successful
	use of this package depends on consistent referencing of the 
	instrinsic's versions of malloc, calloc, etc.  Environment 
	variables can be used to customize the control and use of the 
	package.

	The package provides checks for the following programmer
	errors:

	UNINITIALIZED MEMORY:
	
	By default, a fill character is written into memory allocated
	by XtMalloc, XtCalloc and XtRealloc as listed below.  This
	fill pattern (by default 0x01) helps in checking for 
	uninitialized memory.

		XtMalloc : all memory malloced is initialized with the 
			   fill pattern.

		XtCalloc : By default, XtCalloc initializes the
			   memory requested with nulls, so no fill
			   pattern is written.

		XtRealloc: XtRealloc guarantees that the previously
			   allocated and used memory will retain its
			   contents, so only the additionally requested
			   memory beyond this amount is initialized
			   with the fill pattern.

	ILLEGAL USE OF FREED MEMORY:

	A fill pattern is written into any memory freed (via XtFree)
	so that if the application subsequently tries to use that 
	memory, the application should die (especially if the memory
	contained addresses).  The default freed fill pattern is 0x03.
	
	The free'd block is filled with a different fill pattern so that
	you can easily determine if you are still using free'd space.
	For example:

		ptr = XtMalloc(20);
		bptr = ptr+10;
		/* Do something useful with bptr */
		...
		XtFree(ptr);

		/*
		 *  Now try to do something useful with bptr.  It
		 *  should be trashed enough so that would cause
		 *  real problems and when debugging, you would see
		 *  that it would be filled with 0x03's.
		 */
		


	WRITING BEYOND END OF REQUESTED MEMORY:

	Additional memory is actually allocated for each call to
	XtMalloc, XtRealloc and XtCalloc (see specifics below) which
	also gets filled with the malloc fill pattern.  

	When the memory is freed, the malloc package checks to see that 
	the additional memory still contains the fill pattern.  If not,
	a warning message is generated.

	This is useful for catching things like:
		ptr = XtMalloc(5);
		ptr[5] = '\0';  

	The extra memory allocated is calculated as follows: 
	(considers alignment issues).  

		XtMalloc:  requested_size + (4 - (requested_size % 4))
		XtRealloc: requested_size + (4 - (requested_size % 4))
		XtCalloc:  (num_elements + 1) * element_size

	The above allocates at least one additional byte to be used
	for checking for writes beyond end of memory.

	Additionally, this malloc package contains replacement functions
	for the bstring(3), string(3) and memory(3) functions which (when 
	operating on data that has been allocated via XtMalloc, etc) will 
	check to make sure that the string or memory function will not 
	write beyond the bounds of the previously allocated memory.  A 
	warning message will be generated if this occurs.
		
	This checking does not occur by default; the environment variable
	MALLOC_CHECK_STRING enables it (set it to 1 or True).

		ptr = XtMalloc(5);
		strcpy(ptr,"123456");  
		/* oops, too much!  wrote two extra chars, '6' and '\0' */

	Note that all output (including errors and warnings) from the 
	malloc library goes to stderr by default.  stderr can be 
	redirected to an output file, if desired or the environment
	variable MALLOC_OUT_FILE can be set.

	The only exception is when the package has been compiled with the
	compile time flag, AUTOMATION turned on, output goes to stdout and
	is reduced.  During AUTOMATION, the only messages which get sent
	to stdout are detected errors and warnings, and these messages
	do not contain specific addresses.   This is because we will not
	be doing actual malloc debugging when running automation.


	MEMORY LEAKAGE:

	Lastly, the package keeps track of what has been XtMalloc'ed,
	etc, and will generate a report of what is currently allocated.
	Therefore, if the report is generated at the end of a program,
	the memory leakage of that program will be listed.


	QA'S USE OF THIS MALLOC LIB
	---------------------------

	The QA test suite will get the malloc functionality for "free"
	by "making" the test directory Makefile with the correct
	flag.  No command line arguments are then required when
	running the tests.

	Therefore, to link /tests/Toolkit/Menus/OptionMenu1 with
	the malloc lib:

	% pwd
	/u1/1.1.1-12.19/tests/Toolkit/Menus
	% make IMAKE_DEFINES="-DDebugLib" Makefile
	% make OptionMenu1


	OTHER INFORMATION
	-----------------

	A routine exists in the malloc library, MallocDump(), which 
	will dump any allocated memory at the time it is called.

	For tests in the QA Test Suite, a MallocDump() will occur
	automatically at the end of the test program.  The "end" of
	a test program is defined as any of the following:

	   - when the following signals occur: SIGTERM, SIGSEGV, SIGINT,
		SIGHUP, SIGQUIT 

	   - when the Exit button in the control dialog box is selected

	   - when Close is selected from the window menu
		**** THIS IS CURRENTLY NOT IMPLEMENTED  ******


	For custom use of turning Malloc checking on and off for
	specific areas, two functions exist: MallocEnable and 
	MallocDisable.  Currently, all MallocEnable does is a MallocInit
	which initializes the environment.  MallocDisable disables
        frees the malloc checking data structures and resets the 
	counters and environment so no checking is done.  Hence,
	malloc checking can be enabled and disabled around a particular
	area to test.

	CONFIGURING MALLOC
	------------------

	You may modify the functionality of the malloc package by
	using the following environment variables:

	  MALLOC_ALLOC_CHAR - The fill character written into malloc'ed
		memory.  Default: 0x01.  

	  MALLOC_FREE_CHAR - The fill character written into free'd
		memory.  Default: 0x03.  

	  MALLOC_OUT_FILE - The file name where all malloc output goes.
		Default: stdout.

	  MALLOC_END_DUMP - Whether to dump out the malloc chain and leak
		information at the "end" of a program  (see above).
		Default: True.  (Allowable values: True, False, true, false,
		1, 0)

	  MALLOC_LOG_INFO - Whether to log mallocs/reallocs/callocs/frees
		when they occur.  Default is False.  (Allowable values: 
		True, False, true, false, 1, 0)

	  MALLOC_CHECK_STRING - Whether to check for problems when 
		string/memory functions are referenced.  Default is
		False.


	IMPLEMENTATION DETAILS REQUIRED FOR HOOKS INTO QA TEST SUITE
	------------------------------------------------------------
	
	(1) libCommon.a sources : 
							DONE?
		---------------------------------------------
		TestInit.c calls MallocInit()		YES
		Pause.c calls MallocExit()		YES
		MallocInit/MallocExit stubs must
		   exist in lib/Common to avoid
		   unresolved references when not 
		   linking with this library.		YES


	(2) config/Motif.tmpl modifications:

   #ifdef DebugLib
     TESTMALLOCSRC = $(TESTSRCLIB)/Malloc
   #endif
	
   #ifdef DebugLib
     TESTMALFNS = $(TESTMALLOCSRC)/MallocInit.o $(TESTMALLOCSRC)/MallocExit.o
     TESTMALLOCLIB = $(TESTMALLOCSRC)/libMalloc.a 
   #endif

	This will insure that the correct MallocInit and MallocExit
	get linked in when using the malloc lib.


	OTHER'S USE OF THIS MALLOC LIB
	------------------------------

	To use this malloc library outside of the QA Test Suite, two
	steps are needed.  The first is to make a call to MallocInit()
	in the beginning of the program being tested and make a call
	to MallocExit() at the end of the program.  The second is
	to link with the malloc library.  (MallocDump may also be
	called.  Note that MallocExit requires a parameter, which
	should be specified to be 0.  MallocExit handles signals
	from invalid terminations of the program, therefore it
	checks the first parameter for the signal reason.

	Note that a side effect of using MallocInit() is that several
	signals will be handled by the malloc library; thereby eliminating
	any previously defined signal by your program.  The signals which
	get defined are: SIGTERM, SIGSEGV, SIGINT,SIGHUP, and SIGQUIT.
	Upon the occurrence of any of these signals, a MallocDump()
	will occur and the program will terminate.	

		
	EXAMPLE
	-------

	This is a simple program which does a few XtMallocs/XtFrees.
	The results of running the program are listed below.


#include <stdio.h>
#include <Malloc.h>

main( argc, argv )
int argc;
char **argv;
{
  
  char *XtCalloc();
  char *XtMalloc();
  void XtFree();
  char *big_area1, *big_area2, *four_bytes, *eight_bytes, *twelve_bytes;
  char *one_meg;
  char *another_meg;

  /* initialize malloc */

  MallocInit();

  big_area1 = XtMalloc(40);	    
  big_area2 = XtMalloc(50);
  four_bytes = XtMalloc(4);
  eight_bytes = XtMalloc(8);

  eight_bytes[6] = '6';
  eight_bytes[7] = '7';
  eight_bytes[8] = '\0';			/* too far! 	 */

  strcpy(&four_bytes[0], &eight_bytes[0]);  	/* bad news :(   */

  XtFree(big_area1);			
  XtFree(big_area2);

  one_meg = XtMalloc(101);
  twelve_bytes = XtMalloc(12);
  another_meg = XtMalloc(102);

  XtFree(twelve_bytes);
  XtFree(one_meg);

  XtFree(another_meg);

  another_meg = XtMalloc(103);
  XtFree(four_bytes);
  XtFree(eight_bytes);

  /* Note that another_meg HAS NOT been freed */

  MallocDump();
}


% make IMAKE_DEFINES="-DDebuglib" Makefile
% make testmalloc
rm -f testmalloc.o
cc -c -g -Wf,-XNh2000 -Olimit 2000 -DSTRINGS_ALIGNED -D_NO_PROTO -DNO_REGEX
-I../../../. -I. -I../../../. -I../../.././lib -I../../.././lib/Xt -I../bitmaps
-I../  -I../../.././tests/lib/Common      testmalloc2.c
rm -f testmalloc
cc -o testmalloc testmalloc.o  ../../.././tests/lib/Malloc/MallocInit.o ../
../.././tests/lib/Malloc/MallocExit.o ../../.././tests/lib/Common/libCommon.a
../../.././lib/Mrm/libMrm.a ../../.././lib/Xm/libXm.a 
../../.././tests/lib/Malloc/libMalloc.a  ../../.././lib/Xt/libXt.a 
../../.././extensions/lib/libXext.a   ../../.././lib/X/libX11.a

% testmalloc

Warning: User overwrote allocated data; detected on free,
          size: 8,address = 0x10016010

*****************  DUMPING LEFTOVER DATA  **********

Leftover 103 bytes at 0x10017080

*****************   MALLOC DATA COUNTS  **********

Total bytes left over = 103
Total malloc ptrs left over = 1
Total Memory allocation = 420
Total Pointers allocated = 8


% setenv MALLOC_LOG_INFO True
% testmalloc

+++Malloc'ed 40 bytes at 0x10014000 address
+++Malloc'ed 50 bytes at 0x10014040 address
+++Malloc'ed 4 bytes at 0x10016000 address
+++Malloc'ed 8 bytes at 0x10016010 address
+++Freed     40 bytes at 0x10014000 address
+++Freed     50 bytes at 0x10014040 address
+++Malloc'ed 101 bytes at 0x10017000 address
+++Malloc'ed 12 bytes at 0x10015000 address
+++Malloc'ed 102 bytes at 0x10017080 address
+++Freed     12 bytes at 0x10015000 address
+++Freed     101 bytes at 0x10017000 address
+++Freed     102 bytes at 0x10017080 address
+++Malloc'ed 103 bytes at 0x10017080 address
+++Freed     4 bytes at 0x10016000 address
Warning: User overwrote allocated data; detected on free,
          size: 8,address = 0x10016010
+++Freed     8 bytes at 0x10016010 address

*****************  DUMPING LEFTOVER DATA  **********

Leftover 103 bytes at 0x10017080

*****************   MALLOC DATA COUNTS  **********

Total bytes left over = 103
Total malloc ptrs left over = 1
Total Memory allocation = 420
Total Pointers allocated = 8

