D is a system programming language and thus allows manual memory management. However, manual memory management is prone to memory-safety errors and thus D uses a garbage collector by default to manage memory allocation.
D provides pointer types T*
like in C:
int a; // a is on the stack
int* b = &a; // b contains address of a
auto c = &a; // c is int* and contains address of a
A new memory block on the heap is allocated using a
new T
expression,
which returns a pointer to the managed memory (when T is a value type):
int* a = new int;
Once the memory referenced by a
isn't referenced anywhere
through any variable in the program, the next garbage collection
cycle will free its memory. By default, the garbage collector may only
run when allocating memory with the GC - for example when evaluating
a new
expression.
GC.collect
(from
core.memory
)
GC.disable
(and re-enabled with GC.enable
)
Memory-safety violations can:
To prevent these, D has a memory-safe subset.
D has three different security levels for functions: @system
, @trusted
, and @safe
.
Unless specified otherwise, the default is @system
, which does not check memory-safety.
@safe
enforces a subset of D that prevents memory bugs from occurring by design.
@safe
code can only call other @safe
or @trusted
functions.
Moreover, explicit pointer arithmetic is forbidden in @safe
code:
void main() @safe {
int a = 5;
int* p = &a;
int* c = p + 5; // error
}
@trusted
functions are manually verified functions, which must have
a memory-safe interface.
Internally they can perform @system
operations.
These allow a bridge between SafeD and the underlying dirty low-level world.