|
Packit |
d28291 |
|
|
Packit |
d28291 |
<html lang="en-us">
|
|
Packit |
d28291 |
<HEAD>
|
|
Packit |
d28291 |
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII" >
|
|
Packit |
d28291 |
<TITLE>Using the Garbage Collector: A simple example</title>
|
|
Packit |
d28291 |
</head>
|
|
Packit |
d28291 |
<BODY>
|
|
Packit |
d28291 |
Using the Garbage Collector: A simple example
|
|
Packit |
d28291 |
The following consists of step-by-step instructions for building and
|
|
Packit |
d28291 |
using the collector. We'll assume a Linux/gcc platform and
|
|
Packit |
d28291 |
a single-threaded application. <FONT COLOR=green>The green
|
|
Packit |
d28291 |
text contains information about other platforms or scenarios.
|
|
Packit |
d28291 |
It can be skipped, especially on first reading</font>.
|
|
Packit |
d28291 |
Building the collector
|
|
Packit |
d28291 |
If you have not so yet, unpack the collector and enter
|
|
Packit |
d28291 |
the newly created directory with
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
tar xvfz gc<version>.tar.gz
|
|
Packit |
d28291 |
cd gc<version>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
You can configure, build, and install the collector in a private
|
|
Packit |
d28291 |
directory, say /home/xyz/gc, with the following commands:
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
./configure --prefix=/home/xyz/gc --disable-threads
|
|
Packit |
d28291 |
make
|
|
Packit |
d28291 |
make check
|
|
Packit |
d28291 |
make install
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
Here the "<TT>make check</tt>" command is optional, but highly recommended.
|
|
Packit |
d28291 |
It runs a basic correctness test which usually takes well under a minute.
|
|
Packit |
d28291 |
<FONT COLOR=green>Other platforms</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
On non-Unix, non-Linux platforms, the collector is usually built by copying
|
|
Packit |
d28291 |
the appropriate makefile (see the platform-specific README in doc/README.xxx
|
|
Packit |
d28291 |
in the distribution) to the file "Makefile", and then typing "make"
|
|
Packit |
d28291 |
(or "nmake" or ...). This builds the library in the source tree. You may
|
|
Packit |
d28291 |
want to move it and the files in the include directory to a more convenient
|
|
Packit |
d28291 |
place.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
If you use a makefile that does not require running a configure script,
|
|
Packit |
d28291 |
you should first look at the makefile, and adjust any options that are
|
|
Packit |
d28291 |
documented there.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
If your platform provides a "make" utility, that is generally preferred
|
|
Packit |
d28291 |
to platform- and compiler- dependent "project" files. (At least that is the
|
|
Packit |
d28291 |
strong preference of the would-be maintainer of those project files.)
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>Threads</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
If you need thread support, configure the collector with
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
--enable-threads=posix --enable-parallel-mark
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
instead of
|
|
Packit |
d28291 |
<TT>--disable-threads</tt>
|
|
Packit |
d28291 |
If your target is a real old-fashioned uniprocessor (no "hyperthreading",
|
|
Packit |
d28291 |
etc.) you will want to omit <TT>--enable-parallel-mark</tt>.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>C++</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
You will need to include the C++ support, which unfortunately tends to
|
|
Packit |
d28291 |
be among the least portable parts of the collector, since it seems
|
|
Packit |
d28291 |
to rely on some corner cases of the language. On Linux, it
|
|
Packit |
d28291 |
suffices to add <TT>--enable-cplusplus</tt> to the configure options.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
Writing the program
|
|
Packit |
d28291 |
You will need a
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
#include "gc.h"
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
at the beginning of every file that allocates memory through the
|
|
Packit |
d28291 |
garbage collector. Call <TT>GC_MALLOC</tt> wherever you would
|
|
Packit |
d28291 |
have call <TT>malloc</tt>. This initializes memory to zero like
|
|
Packit |
d28291 |
<TT>calloc</tt>; there is no need to explicitly clear the
|
|
Packit |
d28291 |
result.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
If you know that an object will not contain pointers to the
|
|
Packit |
d28291 |
garbage-collected heap, and you don't need it to be initialized,
|
|
Packit |
d28291 |
call <TT>GC_MALLOC_ATOMIC</tt> instead.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
A function <TT>GC_FREE</tt> is provided but need not be called.
|
|
Packit |
d28291 |
For very small objects, your program will probably perform better if
|
|
Packit |
d28291 |
you do not call it, and let the collector do its job.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
A <TT>GC_REALLOC</tt> function behaves like the C library <TT>realloc</tt>.
|
|
Packit |
d28291 |
It allocates uninitialized pointer-free memory if the original
|
|
Packit |
d28291 |
object was allocated that way.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
The following program <TT>loop.c</tt> is a trivial example:
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
#include "gc.h"
|
|
Packit |
d28291 |
#include <assert.h>
|
|
Packit |
d28291 |
#include <stdio.h>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
int main()
|
|
Packit |
d28291 |
{
|
|
Packit |
d28291 |
int i;
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
GC_INIT();
|
|
Packit |
d28291 |
for (i = 0; i < 10000000; ++i)
|
|
Packit |
d28291 |
{
|
|
Packit |
d28291 |
int **p = (int **) GC_MALLOC(sizeof(int *));
|
|
Packit |
d28291 |
int *q = (int *) GC_MALLOC_ATOMIC(sizeof(int));
|
|
Packit |
d28291 |
assert(*p == 0);
|
|
Packit |
d28291 |
*p = (int *) GC_REALLOC(q, 2 * sizeof(int));
|
|
Packit |
d28291 |
if (i % 100000 == 0)
|
|
Packit |
d28291 |
printf("Heap size = %d\n", GC_get_heap_size());
|
|
Packit |
d28291 |
}
|
|
Packit |
d28291 |
return 0;
|
|
Packit |
d28291 |
}
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>Interaction with the system malloc</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
It is usually best not to mix garbage-collected allocation with the system
|
|
Packit |
d28291 |
<TT>malloc-free</tt>. If you do, you need to be careful not to store
|
|
Packit |
d28291 |
pointers to the garbage-collected heap in memory allocated with the system
|
|
Packit |
d28291 |
<TT>malloc</tt>.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>Other Platforms</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
On some other platforms it is necessary to call <TT>GC_INIT()</tt> from the main program,
|
|
Packit |
d28291 |
which is presumed to be part of the main executable, not a dynamic library.
|
|
Packit |
d28291 |
This can never hurt, and is thus generally good practice.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>Threads</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
For a multi-threaded program, some more rules apply:
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
Files that either allocate through the GC or make thread-related calls
|
|
Packit |
d28291 |
should first define the macro <TT>GC_THREADS</tt>, and then
|
|
Packit |
d28291 |
include <TT>"gc.h"</tt>. On some platforms this will redefine some
|
|
Packit |
d28291 |
threads primitives, e.g. to let the collector keep track of thread creation.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>C++</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
In the case of C++, you need to be especially careful not to store pointers
|
|
Packit |
d28291 |
to the garbage-collected heap in areas that are not traced by the collector.
|
|
Packit |
d28291 |
The collector includes some alternate interfaces
|
|
Packit |
d28291 |
to make that easier.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>Debugging</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
Additional debug checks can be performed by defining <TT>GC_DEBUG</tt> before
|
|
Packit |
d28291 |
including <TT>gc.h</tt>. Additional options are available if the collector
|
|
Packit |
d28291 |
is also built with <TT>--enable-gc-debug</tt> (<TT>--enable-full-debug</tt> in
|
|
Packit |
d28291 |
some older versions) and all allocations are
|
|
Packit |
d28291 |
performed with <TT>GC_DEBUG</tt> defined.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>What if I can't rewrite/recompile my program?</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
You may be able to build the collector with <TT>--enable-redirect-malloc</tt>
|
|
Packit |
d28291 |
and set the <TT>LD_PRELOAD</tt> environment variable to point to the resulting
|
|
Packit |
d28291 |
library, thus replacing the standard <TT>malloc</tt> with its garbage-collected
|
|
Packit |
d28291 |
counterpart. This is rather platform dependent. See the
|
|
Packit |
d28291 |
leak detection documentation for some more details.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
Compiling and linking
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
The above application <TT>loop.c</tt> test program can be compiled and linked
|
|
Packit |
d28291 |
with
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
cc -I/home/xyz/gc/include loop.c /home/xyz/gc/lib/libgc.a -o loop
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
The <TT>-I</tt> option directs the compiler to the right include
|
|
Packit |
d28291 |
directory. In this case, we list the static library
|
|
Packit |
d28291 |
directly on the compile line; the dynamic library could have been
|
|
Packit |
d28291 |
used instead, provided we arranged for the dynamic loader to find
|
|
Packit |
d28291 |
it, e.g. by setting <TT>LD_LIBRARY_PATH</tt>.
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
<FONT COLOR=green>Threads</font>
|
|
Packit |
d28291 |
<FONT COLOR=green>
|
|
Packit |
d28291 |
On pthread platforms, you will of course also have to link with
|
|
Packit |
d28291 |
<TT>-lpthread</tt>,
|
|
Packit |
d28291 |
and compile with any thread-safety options required by your compiler.
|
|
Packit |
d28291 |
On some platforms, you may also need to link with <TT>-ldl</tt>
|
|
Packit |
d28291 |
or <TT>-lrt</tt>.
|
|
Packit |
d28291 |
Looking at tools/threadlibs.c should give you the appropriate
|
|
Packit |
d28291 |
list if a plain <TT>-lpthread</tt> doesn't work.
|
|
Packit |
d28291 |
</font>
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
Running the executable
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
The executable can of course be run normally, e.g. by typing
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
./loop
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
|
|
Packit |
d28291 |
The operation of the collector is affected by a number of environment variables.
|
|
Packit |
d28291 |
For example, setting <TT>GC_PRINT_STATS</tt> produces some
|
|
Packit |
d28291 |
GC statistics on stdout.
|
|
Packit |
d28291 |
See <TT>README.environment</tt> in the distribution for details.
|
|
Packit |
d28291 |
</body>
|
|
Packit |
d28291 |
</html>
|