# MulleObjC Memory Management Modes: Understanding Mode 0, Mode 1, and Mode 2

> Explore MulleObjC's memory management modes 0 1 and 2. Understand how MulleObjC scales from full Objective-C reference counting to pure C environments without runtime overhead.

- Repository: [mulle-objc/mulleobjc](https://github.com/mulle-objc/mulleobjc)
- Tags: internals
- Published: 2026-03-07

---

**MulleObjC supports three distinct memory management modes that scale from full Objective-C reference counting (Mode 0) down to pure C environments without any runtime overhead (Mode 2), configurable at universe initialization time via the `retain_autorelease` flag.**

The mulle-objc/mulleobjc repository implements a flexible runtime architecture that allows developers to select precisely how much Objective-C memory management overhead they require. By configuring one of three distinct memory management modes at universe initialization time, you can deploy everything from high-level object-oriented applications to bare-metal C code using the same toolchain.

## Understanding the Three MulleObjC Memory Management Modes

The definitive specification resides in [`dox/HIERARCHY-OF-LANGUAGE-FEATURES.md`](https://github.com/mulle-objc/mulleobjc/blob/main/dox/HIERARCHY-OF-LANGUAGE-FEATURES.md), which categorizes the modes by enabled language features and runtime availability.

### Mode 0: Full Objective-C Runtime Semantics

Mode 0 represents the complete Objective-C memory model with all standard reference counting primitives available. In this configuration, `retain`, `release`, and `autorelease` methods are fully implemented, and `@autoreleasepool` blocks function normally. The complete suite of language constructs—including `@defs` and `@encode`—remain operational. According to the source documentation, Mode 0 is defined as the "Can do anything" configuration, making it suitable for normal application development where you require the complete ObjC memory model.

### Mode 1: C-Style Without Reference Counting

Mode 1 strips away all Objective-C memory management helpers while maintaining basic runtime structure. The documentation explicitly states that this mode enforces "No retain/release/autorelease" and "No @autoreleasepool". Code in Mode 1 restricts itself to plain C types and functions, making it appropriate for low-level libraries or freestanding environments that must operate without automatic reference counting overhead or autorelease pool machinery.

### Mode 2: Minimal C-Only Environment

Mode 2 provides the most constrained execution environment, reducing available abstractions to raw memory primitives. Beyond disabling all Objective-C memory management features found in Mode 1, this configuration limits useful operations to "C pointers", "Copying C structs", and "C integer datatypes" as documented in the hierarchy specification. This mode targets highly constrained embedded systems or kernel-like environments where only raw pointers and scalar values are permitted.

## How Memory Management Modes Are Configured in MulleObjC

The mode selection occurs at **universe configuration time** through the `MulleObjCUniverse` structure defined in [`src/MulleObjCUniverse.h`](https://github.com/mulle-objc/mulleobjc/blob/main/src/MulleObjCUniverse.h). This structure contains a critical `retain_autorelease` flag that determines the runtime's behavior.

When `retain_autorelease` is enabled, the runtime operates in **Mode 0**, providing full `retain`/`release`/`autorelease` implementations as implemented in `src/protocol/MulleObjCRootObject.m`. Clearing this flag transitions the runtime to **Mode 1**, eliminating reference counting primitives. For **Mode 2** compliance, the flag is removed entirely during build configuration, producing a pure-C binary that excludes the MulleObjC runtime library altogether.

The implementation of these runtime switches resides in `src/mulle-objc-universeconfiguration.m`, which handles the conditional compilation and linking requirements for each mode.

## Code Examples for Each MulleObjC Memory Mode

### Mode 0: Standard Objective-C Reference Counting

```objc
#import <MulleObjC/MulleObjC.h>

int main(void)
{
    @autoreleasepool {
        NSString *s = [@"Hello" retain];
        printf("%s\n", [s UTF8String]);
        [s release];   // explicit release, safe inside autoreleasepool
    }
    return 0;
}

```

This example requires the default universe configuration where `retain_autorelease` is enabled.

### Mode 1: Pure C Allocation Without ObjC Runtime

```c
#include <mulle-objc-runtime.h>

int main(void)
{
    // No `retain` / `release` functions are available.
    // Use plain C allocation instead.
    struct MyStruct {
        int value;
    } *obj = malloc(sizeof(struct MyStruct));
    obj->value = 42;
    printf("%d\n", obj->value);
    free(obj);
    return 0;
}

```

To enforce Mode 1, set `MULLE_OBJC_RETAIN_AUTORELEASE=0` in the universe configuration via `src/mulle-objc-universeconfiguration.m`.

### Mode 2: Raw C Pointers Only

```c
/* No ObjC headers at all – the build must exclude the ObjC runtime. */
int main(void)
{
    int *p = (int *)malloc(sizeof(int));
    *p = 123;
    printf("%d\n", *p);
    free(p);
    return 0;
}

```

This Mode 2 example uses only raw pointers and scalar types, with the project built without linking the MulleObjC runtime library.

## Key Source Files Controlling Memory Management

Understanding these implementation files clarifies how the modes function:

- **[`src/MulleObjCUniverse.h`](https://github.com/mulle-objc/mulleobjc/blob/main/src/MulleObjCUniverse.h)**: Defines the universe configuration structure containing the `retain_autorelease` flag that selects between Mode 0 and Mode 1.
- **`src/mulle-objc-universeconfiguration.m`**: Implements the runtime switches and initialization logic for retain/release and autorelease functionality.
- **[`dox/HIERARCHY-OF-LANGUAGE-FEATURES.md`](https://github.com/mulle-objc/mulleobjc/blob/main/dox/HIERARCHY-OF-LANGUAGE-FEATURES.md)**: Contains the official documentation specifying which features are available in each mode.
- **[`src/MulleObjC.h`](https://github.com/mulle-objc/mulleobjc/blob/main/src/MulleObjC.h)**: The central header exposing the public API; its available symbols change based on the selected mode.
- **`src/protocol/MulleObjCRootObject.m`**: Houses the actual `retain`/`release`/`autorelease` implementations used exclusively in Mode 0.

## Summary

- **Mode 0** provides full Objective-C reference counting with `retain`, `release`, `autorelease`, and `@autoreleasepool` for standard application development.
- **Mode 1** disables all reference counting primitives and autorelease pools, restricting code to C-style memory management suitable for low-level libraries.
- **Mode 2** creates a minimal C-only environment supporting only raw pointers, struct copying, and integer datatypes for embedded or kernel contexts.
- Mode selection occurs at universe configuration time via the `retain_autorelease` flag in `MulleObjCUniverse`.
- The `mulle-objc/mulleobjc` repository implements these modes through conditional compilation in `src/mulle-objc-universeconfiguration.m` and selective header inclusion.

## Frequently Asked Questions

### How do I switch between MulleObjC memory management modes?

You configure the mode at universe initialization by modifying the `retain_autorelease` flag in the `MulleObjCUniverse` structure defined in [`src/MulleObjCUniverse.h`](https://github.com/mulle-objc/mulleobjc/blob/main/src/MulleObjCUniverse.h). Set the flag to enable Mode 0, clear it for Mode 1, or exclude the runtime entirely for Mode 2. This configuration is typically handled in `src/mulle-objc-universeconfiguration.m` or through build-time preprocessor definitions.

### Can I use Objective-C objects in Mode 1 or Mode 2?

No. Mode 1 explicitly disables Objective-C objects that rely on automatic reference counting, while Mode 2 removes the Objective-C runtime completely. These modes are designed for pure C code where you manage memory manually with `malloc` and `free`, or for environments where the Objective-C runtime is unavailable.

### Which memory management mode should I choose for embedded systems?

For highly constrained embedded or kernel-like environments, **Mode 2** is the appropriate choice. It eliminates all runtime overhead and restricts operations to raw pointers and scalar values as specified in [`dox/HIERARCHY-OF-LANGUAGE-FEATURES.md`](https://github.com/mulle-objc/mulleobjc/blob/main/dox/HIERARCHY-OF-LANGUAGE-FEATURES.md). If you need basic C structs but can tolerate minimal runtime support, Mode 1 offers a middle ground, while Mode 0 is too heavyweight for bare-metal deployment.

### Where is the definitive documentation for these modes?

The authoritative specification lives in [`dox/HIERARCHY-OF-LANGUAGE-FEATURES.md`](https://github.com/mulle-objc/mulleobjc/blob/main/dox/HIERARCHY-OF-LANGUAGE-FEATURES.md) within the mulle-objc/mulleobjc repository. This document explicitly lists the enabled and disabled features for each mode, while the implementation details reside in [`src/MulleObjCUniverse.h`](https://github.com/mulle-objc/mulleobjc/blob/main/src/MulleObjCUniverse.h) and `src/mulle-objc-universeconfiguration.m`.