# Boehm GC: a conservative collector that predates your build system

> The Boehm-Demers-Weiser collector is three decades of conservative mark-and-sweep in C, shipping parallel autotools, CMake and Zig build paths, a C++ interface and a manual page, with three release lines patched on the same day in February 2026.

**bdwgc/bdwgc** — The Boehm-Demers-Weiser conservative C/C++ Garbage Collector (bdwgc, also known as bdw-gc, boehm-gc, libgc)

- Repository: https://github.com/bdwgc/bdwgc
- Website: https://github.com/bdwgc/bdwgc/wiki
- Stars: 3,545 · Forks: 445
- Language: C
- License: NOASSERTION
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/bdwgc-bdwgc

## Version 8.3.0 in development, with 8.2.12 as the usable release

The README opens with an unusual pair of statements: this is version 8.3.0, next release development, and a more recent or stable version may exist on the project's Download page or the upstream BDWGC site. That framing is the first useful fact about the repository. What you clone from GitHub is the working edge, not the artifact you should ship.

The GitHub releases confirm it. Three tags appear, and they are not successive versions of one line. v8.2.12 was published on 2026-02-05, v8.0.18 on the same day hours earlier, and v7.6.26 on 2026-02-04. Three release lines patched within about a day of each other is a maintenance posture for a library embedded in long-lived software, where you cannot ask every downstream user to upgrade in lockstep.

The release bodies read like a portability ledger rather than a feature list. In v8.2.12 the entries include fixing a KERN_PROTECTION_FAILURE while world is stopped error on macOS, fixing a cycle in the NORMAL freelist if malloc is redirected on Linux, fixing a race in DllMain by deferring delete_thread to the collector, and a batch of gcc and clang warning eliminations on Solaris, Serenity, Windows and OpenBSD alpha. Compiler warnings about unused parameters and incompatible function pointer casts get their own lines. That is what thirty-plus years of production use looks like from the inside: every entry is somebody's bug report from a platform you do not run.

## Conservative scanning, and why it needs no pointer annotations

The README describes the collector as general purpose and, on the licensing line, MIT-style. The algorithm is where the project earns its name and its longevity. Rather than requiring the program to declare which words hold pointers, a conservative collector scans memory such as thread stacks and registers and treats any word that looks like a plausible address as a live reference.

The README is candid about the ancestry here. It credits run-time systems at Xerox PARC in the early 1980s for conservatively scanning thread stacks to locate possible pointers, citing Paul Rovner's thesis, and names Doug McIlroy as having written a simpler fully conservative collector. It also flags the compiler interaction problem directly, listing Boehm and Chase's 'A Proposal for GC-safe C Compilation' from 1992 and Boehm's 'Simple GC-safe Compilation' from SIGPLAN '96.

Four primary papers anchor the design, and the years matter: Boehm and Weiser in Software Practice and Experience in 1988 on collection in an uncooperative environment, Boehm, Demers and Shenker at SIGPLAN '91 on mostly parallel garbage collection, Boehm at SIGPLAN '93 on space-efficient conservative collection, and his 2000 memory management paper on reducing collector cache misses. A reader choosing between collectors should notice what is absent from that list: nothing about precise typing or generational collection.

The trade is the one every conservative collector makes. You lose precision, you cannot collect everything, and retained garbage is normal. In exchange, unmodified C and C++ code participates without annotation.

## Stop-the-world by default, incremental and parallel on request

One README paragraph covers the operational model, and it is worth reading closely because it sets expectations before you build anything. Unlike the collector in the second reference, this one operates either with the mutator stopped during the entire collection, which is the default, or incrementally during allocations, and the README notes the incremental mode is supported on fewer machines. On the most common platforms it can be built with or without multi-threading support, and on some platforms it can use a multiprocessor to speed up collection.

So there are three axes to configure, and each is a separate decision. Stop-the-world versus incremental changes latency shape. Thread support changes whether a threaded application needs explicit registration calls. Multiprocessor use changes how much wall-clock pause you trade for hardware.

A note on the stop-the-world name: the C source names it plainly. `pthread_stop_world.c` and `pthread_support.c` sit at the root of the tree beside `darwin_stop_world.c`, and the macOS crash fix in the release notes refers to the world being stopped. If you have seen that phrase elsewhere and assumed it describes every garbage collector, this is the file that gives it a concrete meaning.

For latency-sensitive C, the honest summary is that the default is the simplest thing that works, and the incremental path is the one that will need measurement on your target machine.

## Four build systems, which tells you how many platforms this targets

The root of the tree is the clearest statement of scope in the repository, because it lists every build path maintained at once: `CMakeLists.txt`, `Makefile.am`, `Makefile.direct`, `configure.ac`, `autogen.sh`, `NT_MAKEFILE`, `WCC_MAKEFILE`, `build.zig` with `build.zig.zon`, plus `.appveyor.yml` and `.travis.yml`.

The README badge row matches that breadth with separate GitHub Actions workflows for autotools, CMake, CMake extra, CMake cosmo, Zig build and test, Zig cross-compile for Linux and for other platforms, a Makefile.direct build, cppcheck, format check, CSA check, spell-check and CodeQL. Travis, AppVeyor, Coverity, Codecov, Coveralls and an OpenSSF Best Practices badge sit alongside them.

The autotools path is the one most Unix projects still use for this library, and it is short:

```bash
git clone https://github.com/bdwgc/bdwgc
cd bdwgc
autogen.sh
./configure
make
```

CMake is the alternative, with `build.zig` and `build.zig.zon` for the newer option. `Makefile.direct` exists for people who want a plain makefile with no configure step, and the `NT_MAKEFILE` and `WCC_MAKEFILE` are the historical entries for Windows toolchains.

Having four build systems is a maintenance cost the project has accepted deliberately, and it is the clearest signal of what kind of adopter this is: software that ships inside other software, on platforms its authors do not control.

## The source tree names the phases, and the extras live in subdirectories

Roughly fifty C and C++ files sit at the root, and reading their names gives a decent map of the collector's stages. `mark.c` and `mark_rts.c` are the marking side, with `mark_rts.c` handling run-time stack scanning for the platform-specific cases. `reclaim.c` is the sweep. Allocation is spread across `malloc.c`, `mallocx.c`, `alloc.c`, `new_hblk.c` and `allchblk.c`, which handles large or multi-block spans.

The interesting outliers are the ones that exist for specific reasons. `blacklst.c` maintains the black list of addresses never to treat as pointers, `ptr_chck.c` checks pointer plausibility, `checksums.c` verifies heap integrity, `dbg_mlc.c` and `fnlz_mlc.c` are the debugging and finalization allocators, and `dyn_load.c` handles dynamically loaded libraries. Platform glue is explicit: `os_dep.c`, `mach_dep.c`, `darwin_stop_world.c`, `ia64_save_regs_in_stack.s` and `sparc_mach_dep.S`.

There are also C++ entry points, `gc_cpp.cc` and `gc_cpp.cpp` with bad-allocation variants, and the topic list carries the leak-detection framing that `dbg_mlc.c` supports.

Three subdirectories matter. `include/` holds the public headers. `cord/` is the cordsets library, a structured-string container built on the collector, with its own console tool referenced in a release note about a missing newline in a help message. `docs/` and `extra/` hold documentation and extra material. The manual page is `gc.man`, at the root.

## Where the documentation actually lives, and what the README leaves out

This is the axis where the repository is thinnest, and the honest version is that the README is an abstract and a citation list, not a manual. It names the algorithms and their papers, states the licensing, points to a Download page, and points to a site at hboehm.info. It says nothing about how to write an allocation call, nothing about build flags, and nothing about configuration macros.

The homepage field confirms where that content moved: the project's wiki at github.com/bdwgc/bdwgc/wiki. For a library of this age that documentation tends to live as wiki pages and a `gc.man` manual page rather than as markdown in the repository, which is consistent with a codebase whose README has stayed a stable front page while the code changed underneath it.

Two consequences for anyone evaluating it. First, you cannot judge configuration cost from the README alone, because the flags that matter, thread registration, incremental mode, blacklisting, finalizers, are all documented elsewhere. Second, the wiki is a moving target tied to whatever version the maintainers consider current, so pinning means reading the wiki at the tag you plan to build.

The project is not archived, and the repository was pushed on 2026-09-23, which is within weeks of this snapshot. With 3538 stars, 445 forks and 189 open issues, the open questions are mostly about porting and platform edge cases rather than about the core algorithm.

## Conclusion

Start here if your program allocates in C or C++, you cannot annotate pointer types at the call site, and you want reclamation without a language runtime. The reasons to pick it are specific: conservative scanning means you do not have to tell the collector which word is a pointer, the build reaches autotools, CMake, Zig, MSVC and a plain makefile, and release 8.2.12 is a working target rather than an aspiration. What it will not do is give you precise types, precise timing or a small footprint, and the manual page in `gc.man` plus the wiki linked as the homepage are where the configuration surface is actually documented. The README in this repository is short, and most of what a user needs is one click beyond it.

## FAQ

### What runs the garbage collector program to free unused memory?

Nothing external and no separate daemon. The collector runs inside your process, during collection cycles your program triggers, and it reclaims blocks that its own tracing shows to be unreachable. The README describes two modes: mutator stopped for the whole collection, which is the default, or incremental work during allocations.

### How does the mark-and-sweep garbage collection algorithm work?

The mark phase traces live references outward from roots and the sweep phase reclaims everything unmarked. In this collector the tracing is conservative, so roots such as thread stacks and registers are scanned and any word that looks like a plausible address is followed, which is why unmodified C code participates without annotations. The phases live in `mark.c`, `mark_rts.c` and `reclaim.c`.

### What triggers garbage collection?

Collections happen inside the program, either at allocation points in incremental mode or as a full stop-the-world cycle, which is the default the README describes. Platform code for the pause is explicit in `pthread_stop_world.c` and `darwin_stop_world.c`, and multi-threading and multiprocessor support are build-time options on the most common platforms.

## Sources

- [bdwgc/bdwgc on GitHub](https://github.com/bdwgc/bdwgc)
- [Issues](https://github.com/bdwgc/bdwgc/issues)
- [Project website](https://github.com/bdwgc/bdwgc/wiki)
- [README](https://github.com/bdwgc/bdwgc/blob/master/README.md)
- [Releases](https://github.com/bdwgc/bdwgc/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/bdwgc-bdwgc
