Memory Management: GC, Manual and RAII

31.1 The Garbage Collector

The default allocator for new, array appends, closures, and associative arrays.

A conservative, stop-the-world, mark-and-sweep GC. It only collects during allocation, so no allocation means no GC pause.

Runtime options: --DRT-gcopt=profile:1 gc:precise parallel:4 initReserve:64 (command line or extern(C) __gshared string[] rt_options).

Alternatives: precise GC (gc:precise), the fork-based concurrent GC on Linux (gc:fork), and new GC work in progress.

import core.memory : GC;
GC.collect();                 // force a collection
GC.disable(); /* ... */ GC.enable();
GC.minimize();
auto stats = GC.stats();
writeln(stats.usedSize, " ", stats.freeSize);
GC.addRoot(ptr); GC.removeRoot(ptr);     // keep C-held pointers alive
GC.addRange(mem, size);                  // scan manually allocated memory

31.2 Manual Memory Management

import core.stdc.stdlib : malloc, free, calloc, realloc;
int* p = cast(int*) malloc(10 * int.sizeof);
scope(exit) free(p);
int[] arr = p[0 .. 10];                  // slice over malloc'd memory

import core.lifetime : emplace;
void[] mem = malloc(__traits(classInstanceSize, MyClass))[0 .. __traits(classInstanceSize, MyClass)];
auto obj = emplace!MyClass(mem, args);   // construct in place
destroy(obj);                            // run the destructor
free(mem.ptr);

31.3 std.experimental.allocator

Composable building blocks: FreeList, Region, StatsCollector, FallbackAllocator, Segregator, AllocatorList, BitmappedBlock.

import std.experimental.allocator;
import std.experimental.allocator.mallocator : Mallocator;
import std.experimental.allocator.building_blocks.region : Region;

auto arr = Mallocator.instance.makeArray!int(100);
scope(exit) Mallocator.instance.dispose(arr);
auto obj = Mallocator.instance.make!Point(1, 2);
scope(exit) Mallocator.instance.dispose(obj);

auto region = Region!Mallocator(1024 * 1024);   // arena-style bump allocator
auto tmp = region.makeArray!ubyte(256);

31.4 RAII and Reference Counting

Container libraries without the GC: automem (unique_ptr/RefCounted for D), emsi_containers, mir-algorithm (rc arrays), dplug:core.

import std.typecons : RefCounted, SafeRefCounted, Unique;
auto rc = SafeRefCounted!Buffer(1024);   // freed when the last copy goes away
auto u = Unique!Resource(new Resource);  // single owner

31.5 @nogc Code

The compiler verifies that no GC allocation happens. -vgc lists all GC allocation points.

@nogc nothrow int sumArr(const int[] a)
{
    int s = 0;
    foreach (x; a) s += x;
    return s;          // `new`, `~`, closures, and exceptions (new Exception) aren't allowed
}