This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/lib/USING
2001-08-17 05:46:24 +00:00

170 lines
6.3 KiB
Plaintext

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.