Using memwatch
==============

What is it?

	Memwatch is primarily a memory leak detector for C. Besides
	detecting leaks, it can do a bunch of other stuff, but lets
	stay to the basics. If you _really_ want to know all the
	gory details, you should check out the header file,
	memwatch.h, and the source code. It's actually got some
	comments! (Whoa, what a concept!)

How do I get the latest version?

	http://www.link-data.com/sourcecode.html
	ftp://ftp.link-data.com/pub/memwatch/

How does it work?

	Using the C preprocessor, memwatch replaces all your
	programs calls to ANSI C memory allocation functions with
	calls to it's own functions, which keeps a record of all
	allocations.
	
	Memwatch is very unobtrusive; unless the define MEMWATCH is
	defined, memwatch removes all traces of itself from the
	code (using the preprocessor).
	
	Memwatch normally writes it's data to the file
	memwatch.log, but this can be overridden; see the section
	on I/O, later.

Initialization and cleanup

	In order to do it's work in a timely fashion, memwatch
	needs to do some startup and cleanup work. mwInit()
	initializes memwatch and mwTerm() terminates it. Memwatch
	can auto-initialize, and will do so if you don't call
	mwInit() yourself. If this is the case, memwatch will use
	atexit() to register mwTerm() to the atexit-queue.
	
	The auto-init technique has a caveat; if you are using
	atexit() yourself to do cleanup work, memwatch may
	terminate before your program is done. To be on the safe
	side, use mwInit() and mwTerm().
	
	mwInit() and mwTerm() is nestable, so you can call mwInit()
	several times, requiring mwTerm() to be called an equal
	number of times to terminate memwatch.
	
	In case of the program aborting in a controlled way, you
	may want to call mwAbort() instead of mwTerm(). mwAbort()
	will terminate memwatch even if there are outstanding calls
	to mwTerm().

I/O operations

	During normal operations, memwatch creates a file named
	memwatch.log. Sometimes, memwatch.log can't be created;
	then memwatch tries to create files name memwatNN.log,
	where NN is between 01 and 99. If that fails, no log will
	be produced.
	
	If you can't use a file log, or don't want to, no worry.
	Just call mwSetOutFunc() with the address of a "void
	func(int c)" function, and all output will be directed
	there, character by character.
	
	Memwatch also has an Abort/Retry/Ignore handler that is
	used when an ASSERT or VERIFY fails. The default handler
	does no I/O, but automatically aborts the program. You can
	use any handler you want; just send the address of a "int
	func(const char*)" to mwSetAriFunc(). For more details on
	that, see memwatch.h.

TRACE/ASSERT/VERIFY macros

	Memwatch defines (if not already defined) the macros TRACE,
	ASSERT and VERIFY. If you are already using macros with
	these names, memwatch 2.61 and later will not override
	them. Memwatch 2.61 and later will also always define the
	macros mwTRACE, mwASSERT and mwVERIFY, so you can use these
	to make sure you're talking to memwatch. Versions previous
	to 2.61 will OVERRIDE TRACE, ASSERT and VERIFY.
	
	To make sure that existing TRACE, ASSERT and VERIFY macros
	are preserved, you can define MW_NOTRACE, MW_NOASSERT and
	MW_NOVERIFY. All versions of memwatch will abide by these.

Stress-testing the application

	You can simulate low-memory conditions using mwLimit().
	mwLimit() takes the maximum number of bytes to be
	allocated; when the limit is hit, allocation requests will
	fail, and a "limit" message will be logged.
	
	If you hit a real low-memory situation, memwatch logs that
	too. Memwatch itself has some reserve memory tucked away so
	it should continue running even in the worst conditions.

Hunting down wild writes and other Nasty Things

	Wild writes are usually caused by using pointers that arent
	initialized, or that were initialized, but then the memory
	they points to is moved or freed. The best way to avoid
	these kind of problems is to ALWAYS initialize pointers to
	NULL, and after freeing a memory buffer, setting all
	pointers that pointed to it to NULL.
	
	To aid in tracking down uninitialized pointers memwatch
	zaps all memory with certain values. Recently allocated
	memory (unless calloc'd, of course), contains 0xFE.
	Recently freed memory contains 0xFD. So if your program
	crashes when using memwatch and not without memwatch, it's
	most likely because you are not initializing your allocated
	buffers, or using the buffers after they've been freed.
	
	In the event that a wild pointer should damage memwatch's
	internal data structures, memwatch employs checksums,
	multiple copies of some values, and can also repair it's
	own data structures.
	
	If you are a paranoid person, and as programmer you should
	be, you can use memwatch's mwIsReadAddr() and
	mwIsSafeAddr() functions to check the accessibility of
	memory. These are implemented for both ANSI C systems and
	Win32 systems. Just put an mwASSERT() around the check and
	forget about it.

Can I help?

	Well, sure. For instance, I like memwatch to compile
	without any warnings or errors. If you are using an ANSI C
	compliant compiler, and are getting warnings or errors,
	please mail me the details and instructions on how to fix
	them, if you can.
	
	Another thing you can do if you decide to use memwatch is
	to mail me the name of the project(s) (and URL, if any),
	hardware and operating system, compiler and what user
	(organization). I will then post this info on the list of
	memwatch users.
	(http://www.link-data.com/memwatchusers.html)

Top five problems using memwatch

	5.  Passed a non-memwatch allocated pointer to memwatch's
		free(). Symtom: Causes an erroneous "WILD free" log
		entry to appear. Cure: Either include memwatch.h for
		the file that allocates, or use mwFree_() to free it.
		
	4.  Relied on auto-initialization when using atexit().
		Symptom: Causes incorrect "unfreed" and "WILD free"
		messages. Cure: Use mwInit() and mwTerm().
		
	3.  Forgot to include memwatch.h in all files. Symptom:
		Tends to generate "WILD free" and "unfreed" messages.
		Cure: Make sure to include memwatch.h!
		
	2.  No write permissions in currect directory. Symptom:
		Seems like memwatch 'just aint working'. Cure: Use
		mwSetOutFunc() to redirect output.
	
	...and the number one problem is...
	
	1.  Didn't define MEMWATCH when compiling. Symptom:
		Memwatch dutifully disables itself. Cure: Try adding
		-DMEMWATCH to the command line.