summaryrefslogtreecommitdiff
path: root/manual/memory.texi
diff options
context:
space:
mode:
Diffstat (limited to 'manual/memory.texi')
-rw-r--r--manual/memory.texi261
1 files changed, 254 insertions, 7 deletions
diff --git a/manual/memory.texi b/manual/memory.texi
index 16dc9aa5e1..a186fd4b8c 100644
--- a/manual/memory.texi
+++ b/manual/memory.texi
@@ -31,6 +31,7 @@ will be freed automatically. @xref{Variable Size Automatic}.
* Dynamic Allocation and C:: How to get different kinds of allocation in C.
* Unconstrained Allocation:: The @code{malloc} facility allows fully general
dynamic allocation.
+* Allocation Debugging:: Finding memory leaks and not freed memory.
* Obstacks:: Obstacks are less general than malloc
but more efficient and convenient.
* Variable Size Automatic:: Allocation of variable-sized blocks
@@ -630,8 +631,12 @@ uses whenever it is called. You should define this function to look
like @code{malloc}; that is, like:
@smallexample
-void *@var{function} (size_t @var{size})
+void *@var{function} (size_t @var{size}, void *@var{caller})
@end smallexample
+
+The value of @var{caller} is the return address found on the stack when
+the @code{malloc} function was called. This value allows to trace the
+memory consumption of the program.
@end defvar
@comment malloc.h
@@ -642,8 +647,12 @@ uses whenever it is called. You should define this function to look
like @code{realloc}; that is, like:
@smallexample
-void *@var{function} (void *@var{ptr}, size_t @var{size})
+void *@var{function} (void *@var{ptr}, size_t @var{size}, void *@var{caller})
@end smallexample
+
+The value of @var{caller} is the return address found on the stack when
+the @code{realloc} function was called. This value allows to trace the
+memory consumption of the program.
@end defvar
@comment malloc.h
@@ -654,8 +663,12 @@ uses whenever it is called. You should define this function to look
like @code{free}; that is, like:
@smallexample
-void @var{function} (void *@var{ptr})
+void @var{function} (void *@var{ptr}, void *@var{caller})
@end smallexample
+
+The value of @var{caller} is the return address found on the stack when
+the @code{free} function was called. This value allows to trace the
+memory consumption of the program.
@end defvar
You must make sure that the function you install as a hook for one of
@@ -797,13 +810,13 @@ Tell @code{malloc} to perform occasional consistency checks on
dynamically allocated memory, and to call @var{abortfn} when an
inconsistency is found. @xref{Heap Consistency Checking}.
-@item void *(*__malloc_hook) (size_t @var{size})
+@item void *(*__malloc_hook) (size_t @var{size}, void *@var{caller})
A pointer to a function that @code{malloc} uses whenever it is called.
-@item void *(*__realloc_hook) (void *@var{ptr}, size_t @var{size})
+@item void *(*__realloc_hook) (void *@var{ptr}, size_t @var{size}, void *@var{caller})
A pointer to a function that @code{realloc} uses whenever it is called.
-@item void (*__free_hook) (void *@var{ptr})
+@item void (*__free_hook) (void *@var{ptr}, void *@var{caller})
A pointer to a function that @code{free} uses whenever it is called.
@item struct mallinfo mallinfo (void)
@@ -811,6 +824,240 @@ Return information about the current dynamic memory usage.
@xref{Statistics of Malloc}.
@end table
+@node Allocation Debugging
+@section Allocation Debugging
+@cindex allocation debugging
+@cindex malloc debugger
+
+An complicated task when programming with languages which do not use
+garbage collected dynamic memory allocation is to find memory leaks.
+Long running programs must assure that dynamically allocated objects are
+freed at the end of their lifetime. If this does not happen the system
+runs out of memory, sooner or later.
+
+The @code{malloc} implementation in the GNU C library provides some
+simple means to detect sich leaks and provide some information to find
+the location. To do this the application must be started in a special
+mode which is enabled by an environment variable. There are no speed
+penalties if the program is compiled in preparation of the debugging if
+the debug mode is not enabled.
+
+@menu
+* Tracing malloc:: How to install the tracing functionality.
+* Using the Memory Debugger:: Example programs excerpts.
+* Tips for the Memory Debugger:: Some more or less clever ideas.
+* Interpreting the traces:: What do all these lines mean?
+@end menu
+
+@node Tracing malloc
+@subsection How to install the tracing functionality
+
+@comment mcheck.h
+@comment GNU
+@deftypefun void mtrace (void)
+When the @code{mtrace} function is called it looks for an environment
+variable named @code{MALLOC_TRACE}. This variable is supposed to
+contain a valid file name. The user must have write access. If the
+file already exists it is truncated. If the environment variable is not
+set or it does not name a valid file which can be opened for writing
+nothing is done. The behaviour of @code{malloc} etc. is not changed.
+For obvious reasons this also happens if the application is install SUID
+or SGID.
+
+If the named file is successfully opened @code{mtrace} installs special
+handlers for the functions @code{malloc}, @code{realloc}, and
+@code{free} (@pxref{Hooks for Malloc}). From now on all uses of these
+functions are traced and protocolled into the file. There is now of
+course a speed penalty for all calls to the traced functions so that the
+tracing should not be enabled during their normal use.
+
+This function is a GNU extension and generally not available on other
+systems. The prototype can be found in @file{mcheck.h}.
+@end deftypefun
+
+@comment mcheck.h
+@comment GNU
+@deftypefun void muntrace (void)
+The @code{muntrace} function can be called after @code{mtrace} was used
+to enable tracing the @code{malloc} calls. If no (succesful) call of
+@code{mtrace} was made @code{muntrace} does nothing.
+
+Otherwise it deinstalls the handlers for @code{malloc}, @code{realloc},
+and @code{free} and then closes the protocol file. No calls are
+protocolled anymore and the programs runs again with the full speed.
+
+This function is a GNU extension and generally not available on other
+systems. The prototype can be found in @file{mcheck.h}.
+@end deftypefun
+
+@node Using the Memory Debugger
+@subsection Example programs excerpts
+
+Even though the tracing functionality does not influence the runtime
+behaviour of the program it is no wise idea to call @code{mtrace} in all
+programs. Just imagine you debug a program using @code{mtrace} and all
+other programs used in the debug sessions also trace their @code{malloc}
+calls. The output file would be the same for all programs and so is
+unusable. Therefore on should call @code{mtrace} only if compiled for
+debugging. A program could therefore start like this:
+
+@example
+#include <mcheck.h>
+
+int
+main (int argc, char *argv[])
+@{
+#ifdef DEBUGGING
+ mtrace ();
+#endif
+ @dots{}
+@}
+@end example
+
+This is all what is needed if you want to trace the calls during the
+whole runtime of the program. Alternatively you can stop the tracing at
+any time with a call to @code{muntrace}. It is even possible to restart
+the tracing again with a new call to @code{mtrace}. But this can course
+unreliable results since there are possibly calls of the functions which
+are not called. Please note that not only the application uses the
+traced functions, also libraries (including the C library itself) use
+this function.
+
+This last point is also why it is no good idea to call @code{muntrace}
+before the program terminated. The libraries are informed about the
+termination of the program only after the program returns from
+@code{main} or calls @code{exit} and so cannot free the memory they use
+before this time.
+
+So the best thing one can do is to call @code{mtrace} as the very first
+function in the program and never call @code{muntrace}. So the program
+traces almost all uses of the @code{malloc} functions (except those
+calls which are executed by constructors of the program or used
+libraries).
+
+@node Tips for the Memory Debugger
+@subsection Some more or less clever ideas
+
+You know the situation. The program is prepared for debugging and in
+all debugging sessions it runs well. But once it is started without
+debugging the error shows up. In our situation here: the memory leaks
+becomes visible only when we just turned off the debugging. If you
+foresee such situations you can still win. Simply use something
+equivalent to the following little program:
+
+@example
+#include <mcheck.h>
+#include <signal.h>
+
+static void
+enable (int sig)
+@{
+ mtrace ();
+ signal (SIGUSR1, enable);
+@}
+
+static void
+disable (int sig)
+@{
+ muntrace ();
+ signal (SIGUSR2, disable);
+@}
+
+int
+main (int argc, char *argv[])
+@{
+ @dots{}
+
+ signal (SIGUSR1, enable);
+ signal (SIGUSR2, disable);
+
+ @dots{}
+@}
+@end example
+
+I.e., the user can start the memory debugger any time he wants if the
+program was started with @code{MALLOC_TRACE} set in the environment.
+The output will of course not show the allocations which happened before
+the first signal but if there is a memory leak this will show up
+nevertheless.
+
+@node Interpreting the traces
+@subsection Interpreting the traces
+
+If you take a look at the output it will look similar to this:
+
+@example
+= Start
+@ [0x8048209] - 0x8064cc8
+@ [0x8048209] - 0x8064ce0
+@ [0x8048209] - 0x8064cf8
+@ [0x80481eb] + 0x8064c48 0x14
+@ [0x80481eb] + 0x8064c60 0x14
+@ [0x80481eb] + 0x8064c78 0x14
+@ [0x80481eb] + 0x8064c90 0x14
+= End
+@end example
+
+What this all means is not really important since the trace file is not
+meant to be read by a human. Therefore no attention is payed to good
+readability. Instead there is a program which comes with the GNU C
+library which interprets the traces and outputs a summary in on
+user-friendly way. The program is called @code{mtrace} (it is in fact a
+Perl script) and it takes one or two arguments. In any case the name of
+the file with the trace must be specified. If an optional precedes the
+name of the trace file this must be the name of the program which
+generated the trace.
+
+@example
+drepper$ mtrace tst-mtrace log
+No memory leaks.
+@end example
+
+In this case the program @code{tst-mtrace} was run and it produced a
+trace file @file{log}. The message printed by @code{mtrace} shows there
+are no problems with the code, all allocated memory was freed
+afterwards.
+
+If we call @code{mtrace} on the example trace given above we would get a
+different outout:
+
+@example
+drepper$ mtrace errlog
+- 0x08064cc8 Free 2 was never alloc'd 0x8048209
+- 0x08064ce0 Free 3 was never alloc'd 0x8048209
+- 0x08064cf8 Free 4 was never alloc'd 0x8048209
+
+Memory not freed:
+-----------------
+ Address Size Caller
+0x08064c48 0x14 at 0x80481eb
+0x08064c60 0x14 at 0x80481eb
+0x08064c78 0x14 at 0x80481eb
+0x08064c90 0x14 at 0x80481eb
+@end example
+
+We have called @code{mtrace} with only one argument and so the script
+has no chance to find out what is meant with the addresses given in the
+trace. We can do better:
+
+@example
+drepper$ mtrace tst-mtrace errlog
+- 0x08064cc8 Free 2 was never alloc'd /home/drepper/tst-mtrace.c:39
+- 0x08064ce0 Free 3 was never alloc'd /home/drepper/tst-mtrace.c:39
+- 0x08064cf8 Free 4 was never alloc'd /home/drepper/tst-mtrace.c:39
+
+Memory not freed:
+-----------------
+ Address Size Caller
+0x08064c48 0x14 at /home/drepper/tst-mtrace.c:33
+0x08064c60 0x14 at /home/drepper/tst-mtrace.c:33
+0x08064c78 0x14 at /home/drepper/tst-mtrace.c:33
+0x08064c90 0x14 at /home/drepper/tst-mtrace.c:33
+@end example
+
+Suddenly the output makes much more sense and the user can see
+immediately where the function calls causing the trouble can be found.
+
@node Obstacks
@section Obstacks
@cindex obstacks
@@ -1442,7 +1689,7 @@ source file that uses @code{obstack_init} (@pxref{Creating Obstacks}).
Most often they are defined as macros like this:
@smallexample
-#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
@end smallexample